This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
(retracting my comment) Re: Non-default ctors, virtual base classes, & multiple inheritance all at once!
Greetings,
After thinking about this topic a bit more, I would like to retract my
comment associating the choice in the picking the default constructor
of virtual base classes in multiple inheritance instances to a
"limitation in the C++ language".
I apologize for drawing this rash conclusion. If I had thought about
it a bit more I would've realized that the above 'policy' is the best
one possible.
Assume the following scenario:
// begin mtor2.cc
// sidster <patrick at boxsoft dot com>
//
#include <iostream>
class A
{
int i;
public:
A( void )
:
i(0)
{ cout << "A(void)" << endl; };
A(int _i)
:
i(_i)
{ cout << "A(int)" << endl; };
A(float _f)
:
i((int)_f)
{ cout << "A(float)" << endl; };
int
get_value( void ) const
{ return this->i; };
};
class B
:
virtual public A
{
public:
B(int _i)
:
A(_i)
{ cout << "B(int) : A(int)" << endl; };
};
class C
:
virtual public A
{
public:
C(float _f)
:
A(_f)
{ cout << "C(float) : A(float)" << endl; };
};
class D
:
public B,
public C
{
public:
D( int _i, float _f )
:
B(_i),
C(_f)
{ cout << "D(void) : B(int) , C(float)" << endl; };
};
class E
:
public B,
public C
{
public:
E( int _i, float _f )
:
B(_i),
C(_f),
A(_i)
{ cout << "E(void) : B(int) , C(float), A(int)" << endl; };
};
class F
:
public B,
public C
{
public:
F( int _i, float _f )
:
B(_i),
C(_f),
A(_f)
{ cout << "F(void) : B(int) , C(float), A(float)" << endl; };
};
int main( int, char** )
{
D d( 8, 4.7 );
cout << "i = " << d.get_value() << endl; // 0
cout << "- - - - - - - - - - - -" << endl;
E e( 18, 9.5 );
cout << "i = " << e.get_value() << endl; // 18
cout << "- - - - - - - - - - - -" << endl;
F f( 18, 9.5 );
cout << "i = " << f.get_value() << endl; // 9
cout << "- - - - - - - - - - - -" << endl;
return 0;
}
// end mtor2.cc
How will the compiler know which constructor of class A to use when
instantiating an instance of class D?
Since only _one_ instance of class A is to be in D and since both
parent classes, B and C, call different constructors of class A?!
Which would _you_ pick?
So I assume the good people working on the C++ standard concluded that
the best policy is to call the default constructor of that virtual base
class unless otherwise specified.
Both classes, E and F, resolve this ambiguity by specifying which
constructor should be favored.
I am curious, does this sound about right? Or are you all thinking
"what's this guy been smokin'"??
Be good,
(this discussion obviously should've been moved to some c++ news group a
while back since it obviously has nothing to do with gcc. However,
since this'll most likely be the last bit in the thread i hope no one
will be 'ticked off' at me for trying to clear things up.)
* sidster (patrick@mail.boxsoft.com) [20000906 09:50]:
>
> Greetings,
>
>
> * Alexandre Oliva (aoliva@redhat.com) [20000906 07:45]:
> >
> > The latter. It is the most derived class that must construct all
> > virtual base classes, even indirect ones. If it doesn't, default
> > constructors are used, even if other base classes specify constructor
> > arguments for virtual bases.
>
>
> If I understand what you are suggesting correctly then it is
> _impossible_ to get the desired behavior with the given code.
>
> Since template <typename X> class HoldX has no knowledge of what
> base classes X might have to even provide constructors to specify
> them in its "mem-initializer-list".
>
> In other words all template classes with template parameter classes
> containing virtual bases classes (direct or indirect) are restricted
> to using/initializing only the default constructors of these virtual
> base classes. ???
>
> I'm not sure about you but this strikes me as /quite odd/!
>
> If this is true ... then there is a HUGE limitation in the C++
> language!
>
>
> I don't think this makes sense at all. Can you please provide us with
> a reference to this behavior/limitation in the standard?
>
>
> The only section I find is the following:
>
>
> [12.6.2 Initializing bases and members]
> //
> // Initialization shall proceed in the following order:
> //
> // - First, and only for the constructor of the most derived class
> // as described below, virtual base classes shall be initialized
> // in the order they appear on a depth-first left-to-right
> // traversal of the directed acyclic graph of base classes, where
> // "left-to-right" is the order of appearance of the base class
> // names in the derived class base-specifier-list.
>
>
> Which seems to be supporting your point. Which, originally I wasn't too
> sure if it actually meant *all virtual base classes* (including direct
> and indirect).
>
> But the more i read the above it is more clear that that is in-fact what
> it means.
>
>
> The only possible way of getting the intended behavior from the given
> code would be to write a "wrapper" class to be the most derived class
> and specify the desired constructors of the virtual base classes in its
> "mem-initializer-list".
>
> Eeeek! Talk about a hack, error prone, tedious and a maintenance
> nightmare!
patrick
--
when i grow up i want to be a famous rock'n roll guitar player
-- steve vai