Virtual inheritance + copy constructor pitfall

  • Thread starter Marcin Kalicinski
  • Start date
M

Marcin Kalicinski

Hi,

Having the following program:

#include <iostream>

struct A
{
A() { std::cout << "A::A()\n"; }
A(const A &) { std::cout << "A::A(const A &)\n"; }
};

struct B: virtual public A
{
B() { std::cout << "B::B()\n"; }
B(const B &b): A(b) { std::cout << "B::B(const B &)\n"; }
};

struct C: public B
{
C() { std::cout << "C::C()\n"; }
C(const C &c): B(c) { std::cout << "C::C(const C &)\n"; }
};

int main()
{
C c;
std::cout << "---\n";
C c2(c);
}

Why does it print:

A::A()
B::B()
C::C()
---
A::A() <--- here
B::B(const B &)
C::C(const C &)

I.e. why is copy constructor for A not called, but default constructor is
called instead?
 
I

Ian Collins

Marcin said:
Hi,

Having the following program:

#include <iostream>

struct A
{
A() { std::cout << "A::A()\n"; }
A(const A &) { std::cout << "A::A(const A &)\n"; }
};

struct B: virtual public A
{
B() { std::cout << "B::B()\n"; }
B(const B &b): A(b) { std::cout << "B::B(const B &)\n"; }
};

struct C: public B
{
C() { std::cout << "C::C()\n"; }
C(const C &c): B(c) { std::cout << "C::C(const C &)\n"; }
};

int main()
{
C c;
std::cout << "---\n";
C c2(c);
}

Why does it print:

A::A()
B::B()
C::C()
---
A::A() <--- here
B::B(const B &)
C::C(const C &)

I.e. why is copy constructor for A not called, but default constructor is
called instead?
You didn't initialise A in C's copy constructor.

Try

(const C &c): B(c), A(c) { std::cout << "C::C(const C &)\n"; }
 
A

Alf P. Steinbach

* Marcin Kalicinski:
Hi,

Having the following program:

#include <iostream>

struct A
{
A() { std::cout << "A::A()\n"; }
A(const A &) { std::cout << "A::A(const A &)\n"; }
};

struct B: virtual public A
{
B() { std::cout << "B::B()\n"; }
B(const B &b): A(b) { std::cout << "B::B(const B &)\n"; }
};

struct C: public B
{
C() { std::cout << "C::C()\n"; }
C(const C &c): B(c) { std::cout << "C::C(const C &)\n"; }
};

int main()
{
C c;
std::cout << "---\n";
C c2(c);
}

Why does it print:

A::A()
B::B()
C::C()
---
A::A() <--- here
B::B(const B &)
C::C(const C &)

I.e. why is copy constructor for A not called, but default constructor is
called instead?

Constructors of virtual base classes have to be called (implicitly, or
explicitly via constructor initializer list) in the most derived class.

Otherwise, in the context of multiple inheritance, where the virtual
base class object is shared between two or more derived class objects,
you could get multiple calls of constructors on the same virtual base
class object, and the ordinary rules for C++ guarantee exactly one
constructor call per object (unless you do Dirty Things).

So your call in B is simply ignored*.


*) This is specified by §12.6.2/6, "a mem-initializer naming a virtual
base class shall be ignored during execution of the constructor of any
class that is not the most derived class."
 
J

Jonathan Mcdougall

Marcin said:
Hi,

Having the following program:

#include <iostream>

struct A
{
A() { std::cout << "A::A()\n"; }
A(const A &) { std::cout << "A::A(const A &)\n"; }
};

struct B: virtual public A
{
B() { std::cout << "B::B()\n"; }
B(const B &b): A(b) { std::cout << "B::B(const B &)\n"; }
};

struct C: public B
{
C() { std::cout << "C::C()\n"; }
C(const C &c): B(c) { std::cout << "C::C(const C &)\n"; }
};

int main()
{
C c;
std::cout << "---\n";
C c2(c);
}

Why does it print:

A::A()
B::B()
C::C()
---
A::A() <--- here
B::B(const B &)
C::C(const C &)

I.e. why is copy constructor for A not called, but default constructor is
called instead?
From Stroustrup's The C++ Programming Language:

"[...] the language ensures that a constructor for a virtual base is
called exactly once. The constructor of a virtual base is invoked
(implictly or explicitly) from the constructor for the complete object
(the constructor for the most derived class)."

That means C is in charge of calling not only B's constructor, but A's
also. Make it:

struct C : public B
{
C(const C &c)
: B(c), A(c)
{
}
};


Jonathan
 

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

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top