C++之虚基类的构造函数
#include <iostream>
using namespace std;
class A {
public:
A(int a_parameters);
int get_a();
private:
int a;
};
A::A(int a_parameters) : a(a_parameters) { cout << "虚基类A构造函数创建" << endl; }
int A::get_a() { return this->a; }
class B : virtual public A {
public:
B(int a_parameters, int b_parameters);
int get_b();
void display();
private:
int b;
};
B::B(int a_parameters, int b_parameters) : A(a_parameters), b(b_parameters) {
cout << "虚派生类B构造函数创建" << endl;
}
int B::get_b() { return this->b; }
void B::display() { cout << "a:" << get_a() << ":b:" << get_b() << endl; }
class C : virtual A {
public:
C(int a_parameters, int c_parameters);
int get_c();
void display();
private:
int c;
};
C::C(int a_parameters, int c_parameters) : A(a_parameters), c(c_parameters) {
cout << "虚派生类C的构造函数创建" << endl;
}
int C::get_c() { return this->c; }
void C::display() { cout << "a:" << get_a() << ":c:" << get_c() << endl; }
class D : public B, public C {
public:
D(int a_parameters, int b_parameters, int c_parameters, int d_parameters);
int get_d();
void display();
private:
int d;
};
//虚继承中,间接的派生类D定义构造函数的时候,需要调用间接虚基类A(),而普通多继承中这样是不合法的。
D::D(int a_parameters, int b_parameters, int c_parameters, int d_parameters) \
: A(a_parameters), B(a_parameters, b_parameters), C(a_parameters, c_parameters), d(d_parameters) {}
int D::get_d() { return this->d; }
void D::display() {
cout << "a:" << get_a() << ":b:" << get_b() << ":c:" << get_c() << ":d:" << get_d() << endl;
}
int main() {
system("chcp 65001");
B b(1, 2);
b.display();
C c(3, 5);
c.display();
D d(6, 7, 8, 9);
d.display();
return 0;
}
输出:
Active code page: 65001
虚基类A构造函数创建
虚派生类B构造函数创建
a:1:b:2
虚基类A构造函数创建
虚派生类C的构造函数创建
a:3:c:5
虚基类A构造函数创建
虚派生类B构造函数创建
虚派生类C的构造函数创建
a:6:b:7:c:8:d:9
上述程序中发现,在间接派生类D定义构造函数的时候,除了调用基类B和基类C的构造函数,还调用了虚基类A的构造函数,这在普通的继承中是非法的。普通的继承中间接派生类不能显示的调用间接基类A的构造函数,因为这样会造成A基类构造函数的多次初始化。
采用了虚基类后,在间接派生类D中只保留一份成员变量a,如果不调用虚基类A的构造函数,任由虚派生类B和C初始化,很有可能初始化成不同的a值,这就会导致编译器出错,不知道该调用哪个实参初始化D中的a值。
构造函数的执行顺序是首先执行虚基类A,再按照D继承时声明的顺序执行的,这和普通的多继承调用构造函数的顺序是一样的,不会由定义D构造函数的顺序决定D::D(int a_parameters, int b_parameters, int c_parameters, int d_parameters) \ : A(a_parameters), B(a_parameters, b_parameters), C(a_parameters, c_parameters), d(d_parameters) {}