I have the following code:
#include <iostream>
using namespace std;
class A {
public:
A() { cout << "A"; }
A(const A&) { cout << "a"; }
};
class B : public virtual A {
public:
B() { cout << "B"; }
B(const B&) { cout << "b"; }
};
class C : public virtual A {
public:
C() { cout << "C"; }
C(const C&) { cout << "c"; }
};
class D : B, C {
public:
D() { cout << "D"; }
D(const D&) { cout << "d"; }
};
And I want to create a D
object and have it print "ABCDabcd"
.
I tried this:
int main()
{
D d;
return 0;
}
But it only prints "ABCD"
, and I don't know how to call the rest of the code.
Any idea?
The ABCD
portion of the output you see is being printed by the default constructors of A
, B
, C
, and D
. When main()
constructs the D
object, it is invoking D
's default constructor, which invokes A
, B
, and C
's default constructors.
The abcd
portion of the output that is missing is printed by the copy constructors of A
, B
, C
, and D
instead. So main()
needs to make a copy of the D
object in order to invoke D
's copy constructor, eg:
int main()
{
D d;
D d2{d}; // or: D d2 = d;
return 0;
}
However, you will notice that the output of this copy will be ABCd
rather than abcd
as expected. This is because D
's copy constructor does not invoke the copy constructors of A
, B
, or C
, it invokes their default constructors instead.
To fix that, you need to add a member initialization list to each copy constructor in order to call non-default base constructors, eg:
class A {
public:
A() { cout << "A"; }
A(const A&) { cout << "a"; }
};
class B : public virtual A {
public:
B() { cout << "B"; }
B(const B &b) : A(b) { cout << "b"; }
};
class C : public virtual A {
public:
C() { cout << "C"; }
C(const C &c) : A(c) { cout << "c"; }
};
class D : public B, C {
public:
D() { cout << "D"; }
D(const D &d) : A(d), B(d), C(d) { cout << "d"; }
};
Then the copy will print abcd
as expected.