Virtual inheritance + copy constructor pitfall



 DEVELOP > c-Plus-Plus > Virtual inheritance + copy constructor pitfall

LINK TO THIS PAGE  


rating :  0   |  0


  Page 1 of 1

1

 
Topic: DEVELOP > c-Plus-Plus
User: "Marcin Kalicinski"
Date: 05 May 2006 07:48:25 PM
Object: Virtual inheritance + copy constructor pitfall
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?
.

User: "Alf P. Steinbach"

Title: Re: Virtual inheritance + copy constructor pitfall 05 May 2006 08:06:52 PM
* 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."
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
.

User: "Jonathan Mcdougall"

Title: Re: Virtual inheritance + copy constructor pitfall 05 May 2006 08:13:46 PM
Marcin Kalicinski wrote:

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
.

User: "Ian Collins"

Title: Re: Virtual inheritance + copy constructor pitfall 05 May 2006 08:01:10 PM
Marcin Kalicinski wrote:

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"; }
--
Ian Collins.
.


  Page 1 of 1

1

 


Related Articles
 

NEWER

pg.1232     pg.940     pg.716     pg.544     pg.412     pg.311     pg.234     pg.175     pg.130     pg.96     pg.70     pg.50     pg.35     pg.24     pg.16     pg.10     pg.6     pg.3     pg.1

OLDER