(retracting my comment) Re: Non-default ctors, virtual base classes, & multiple inheritance all at once!

sidster patrick@mail.boxsoft.com
Wed Sep 6 20:00:00 GMT 2000


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


More information about the Gcc mailing list