问题
I have the following problem:
struct A1 {
A1() { std::cout << "A1, "; }
};
struct A2 {
A2() { std::cout << "A2, "; }
};
struct AA1 : virtual A1, A2 {
AA1() { std::cout << "AA1, "; }
};
struct AA2 : A1, virtual A2 {
AA2(){ std::cout << "AA2, "; }
};
struct B : AA1, virtual AA2 {
B() { std::cout << "B "; }
};
int main() {
B b;
}
When you run this code, the answer is:
A1 A2 A1 AA2 A2 AA1 B
I want to understand where is the first A1
created.
I know the rule that the virtual classes are called before non - virtual classes but that first A1 is the problem that is bothering me.
回答1:
The first A1
results from the initialization of the (virtual) base of the (non-virtual) base AA1
of B
.
All the virtual bases of B
are initialized first, and they are, in order, A1
, A2
and AA2
. (The initialization of AA2
results in the output A1 AA2
.) Then come the direct bases, of which there is only one, AA1
(whose initialization prints A2 AA1
), and finally the class itself, printing B
. All the virtual bases come first, and then only the remaining non-virtual ones.
回答2:
B
has three virtual base classes: A1
, A2
and AA2
, and according to their order of appearance, it will initialize them in this order.
The first A1
and A2
you see are the initializing of the virtual base A1
and A2
, but the last virtual base AA2
has a non-virtual base A1
, so before constructing AA2
, you'll need to construct another A1
, which is why you have another A1
before AA2
.
You can visualize this by running the following snippet:
#include <iostream>
struct A1 {
A1(const char *s) { std::cout << "A1(" << s << ")\n"; }
};
struct A2 {
A2(const char *s) { std::cout << "A2(" << s << ")\n"; }
};
struct AA1 : virtual A1, A2 {
AA1(const char *s) : A1("AA1"), A2("AA1") { std::cout << "AA1(" << s << ")\n"; }
};
struct AA2 : A1, virtual A2 {
AA2(const char *s) : A1("AA2"), A2("AA2") { std::cout << "AA2(" << s << ")\n"; }
};
struct B : AA1, virtual AA2 {
B() : A1("B"), A2("B"), AA1("B"), AA2("B") { std::cout << "B()\n"; }
};
int main() {
B b;
}
This will output:
A1(B)
A2(B)
A1(AA2)
AA2(B)
A2(AA1)
AA1(B)
B()
You can also notice that this code gives you warning because:
- I put
A1
beforeA2
inAA2
's constructor, butA2
will be initialized beforeA1
(because it is a virtual base andA1
is not). - I put
AA1
beforeAA2
inB
's constructor, butAA2
will be initialized first (same reason).
来源:https://stackoverflow.com/questions/42319938/virtual-base-classes-order-of-creation