diamond inheritance hides non-default constructor

T

Tom

Hello, I've searched groups and the std unsuccessfully for an explanation
of the following - I'd appreciate any comments you may have.

Given the following diamond multiple inheritance pattern, with the base
class having 2 constructors, only the default constructor is called. Is
there a way to require the other constructor to be used?

First, the output:

Base default constructor
Derived1:
Derived2:
Join:
Main:

class Base
{
public:
Base ()
{ cout << "Base default constructor" << endl; }
Base (string const & useMsg)
: msg (useMsg)
{ cout << "Base: " << msg << endl; }
virtual ~Base() {}
string msg;
};

class Derived1 : virtual public Base
{
public:
Derived1 (string const & useMsg)
: Base (useMsg)
{ cout << "Derived1: " << msg << endl; }
};

class Derived2 : virtual public Base
{
public:
Derived2 ()
: Base ()
{ cout << "Derived2: " << msg << endl; }
};

class Join : public Derived1, public Derived2
{
public:
Join ()
: Derived1 ( string ("Hello") ), Derived2 ()
{ cout << "Join: " << msg << endl; }
};

int main ()
{
Join join;
cout << "Main: " << join.msg << endl;
return 0;
}
 
J

JKop

class Join : public Derived1, public Derived2
{
public:
Join ()
: Derived1 ( string ("Hello") ), Derived2 ()
{ cout << "Join: " << msg << endl; }
};

Join() : Derived1( "Hello" ), Derived2(), Base("this is what I was
missing!")
{

}


-JKop
 
V

Victor Bazarov

Tom said:
Hello, I've searched groups and the std unsuccessfully for an explanation
of the following - I'd appreciate any comments you may have.

Given the following diamond multiple inheritance pattern, with the base
class having 2 constructors, only the default constructor is called. Is
there a way to require the other constructor to be used?

First, the output:

Base default constructor
Derived1:
Derived2:
Join:
Main:

class Base
{
public:
Base ()
{ cout << "Base default constructor" << endl; }
Base (string const & useMsg)
: msg (useMsg)
{ cout << "Base: " << msg << endl; }
virtual ~Base() {}
string msg;
};

class Derived1 : virtual public Base
{
public:
Derived1 (string const & useMsg)
: Base (useMsg)
{ cout << "Derived1: " << msg << endl; }
};

class Derived2 : virtual public Base
{
public:
Derived2 ()
: Base ()
{ cout << "Derived2: " << msg << endl; }
};

class Join : public Derived1, public Derived2
{
public:
Join ()
: Derived1 ( string ("Hello") ), Derived2 ()
{ cout << "Join: " << msg << endl; }
};

int main ()
{
Join join;
cout << "Main: " << join.msg << endl;
return 0;
}


Virtual base class initialisation is done at the level of the most derived
class. In your case the 'Join' c-tor should have

Base(???)

in its initialiser list (along with other things). Replace the ??? with
the appropriate expression you want to be evaluated and passed to the
Base's c-tor. I suspect it will be

Base("Hello")

Victor
 
T

Tom

Thanks for your answers.
I finally found your quote in the std doc under initialization (section 12),
not in the section on inheritance (section 10). The explanation is in the
sentence following your quote of it:

All sub-objects representing virtual base classes are initialized by
the constructor of the most derived class. If the constructor of
the most derived class does not specify a mem-initializer for a
virtual base class V, then V's default constructor is called to
initialize the virtual base class subobject.

Tom
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,576
Members
45,054
Latest member
LucyCarper

Latest Threads

Top