Reputation: 5824
Consider this piece of code:
#include <iostream>
class A {
public:
A(int s) { std::cout << "A(" << s << ")\n"; }
};
class B1 : virtual public A {
public:
B1(int s1, int s2)
: A{s1} { std::cout << "B1(" << s1 << "," << s2 << ")\n"; }
};
class B2 : virtual public A {
public:
B2(int s1, int s2)
: A{s1} { std::cout << "B2(" << s1 << "," << s2 << ")\n"; }
};
class C1 : public B1, public B2 {
public:
C1() : B1{1,2}, B2{3,4}, A{5} {}
};
class C2 : public B1, public B2 {
public:
C2() : B1(1,2), B2(3,4), A{5} {}
};
int main()
{
std::cout << "Create c1:\n";
C1 c1;
std::cout << "\n";
std::cout << "Create c2:\n";
C2 c2;
}
Class A is a virtual base class of B1 and B2. Classes C1 and C2 are identical, except that C1 uses {...}
and C2 uses (...)
to construct B1 and B2.
Because of the virtual inheritance used here, class A should be constructed as part of the construction of C1 or C2.
If I compile this code with Microsoft VS2015, it produces this output when running:
Create c1:
A(5)
B1(1,2)
B2(3,4)
Create c2:
A(5)
B1(1,2)
B2(3,4)
which is exactly what I would expect.
But if I compile it with GCC (6.1.0) it produces this output:
Create c1:
A(5)
A(1)
B1(1,2)
A(3)
B2(3,4)
Create c2:
A(5)
B1(1,2)
B2(3,4)
Here, A's constructor is called three times when constructing c1, but only once when constructing c2.
Is this a bug in GCC or have I misunderstood something?
Upvotes: 4
Views: 134
Reputation: 5824
Answering my own question:
Apparently, GCC does have a bug in this case. Compiling the code with GCC version 7.0.0 produces the correct behaviour with this output:
Create c1:
A(5)
B1(1,2)
B2(3,4)
Create c2:
A(5)
B1(1,2)
B2(3,4)
Upvotes: 1
Reputation: 23
The bug is much worse:
#include <iostream>
class A {
public:
A(int s) { std::cout << "A(" << s << ")\n"; ms = s; };
int ms;
virtual void dummy() {std::cout << "Aaaaaa!" << std::endl;};
virtual ~A() {std::cout << "~A(" << ms << ")\n";};
};
class B1 : virtual public A {
public:
B1(int s1, int s2)
: A{s1} { std::cout << "B1(" << s1 << "," << s2 << ")\n"; };
};
class B2 : virtual public A {
public:
B2(int s1, int s2)
: A{s1} { std::cout << "B2(" << s1 << "," << s2 << ")\n"; };
};
class C1 : public B1, public B2 {
public:
C1() : B1{1,2}, B2{3,4}, A{5} {};
};
class C2 : public B1, public B2 {
public:
C2() : B1(1,2), B2(3,4), A{5} {};
};
int main()
{
{
std::cout << "Create c1:\n";
C1 c1;
std::cout << "Calling A's dummy on c1: " << std::endl;
c1.dummy();
std::cout << "Size of c1: " << sizeof(c1) << std::endl;
}
{
std::cout << "\n";
std::cout << "Create c2:\n";
C2 c2;
std::cout << "Calling A's dummy on c2: " << std::endl;
c2.dummy();
std::cout << "Size of c2: " <<sizeof(c2) << std::endl;
}
}
Compiled on GCC 5.4.0 Running this code produced the following output:
Upvotes: 0
Reputation: 23
Not quite sure why is it so, but shouldn't A class be polymorphic (have at least one virtual function) to properly virtually inherit from it?!
Upvotes: 0