虚基类的初始化与一般的多继承的初始化在语法上是一样的,但构造函数的执行顺序不同,主要有以下几点:
1.虚基类的构造函数的执行在非虚蕨类的构造函数之前。
2.若同一层次中包含多个虚基类,这些虚基类的构造函数按照他们被声明的先后次序执行。
3.若虚基类由非虚基类派生而来,则仍然先执行基类的构造函数,再执行派生类的构造函数。
#include<iostream> using namespace std; class Base{ int x; public: Base(int y1) { x=y1; cout<<"Constructing Base, x= "<<x<<endl; } ~Base() { cout<<"Destructing Base"<<endl; } }; class Base1:virtual public Base { int y; public: Base1(int x1,int y1):Base(x1) { y=y1; cout<<"Constructing Base1, y= "<<y1<<endl; } ~Base1() { cout<<"Destructing Base1"<<endl; } }; class Base2:virtual public Base { int z; public: Base2(int x1,int z1):Base(x1) { z=z1; cout<<"Constructing Base2, z= "<<z<<endl; } ~Base2() { cout<<"Destructing Base2"<<endl; } }; class Derived: public Base2,public Base1//基类之间构造函数的执行顺序是严格按照声明时从左到右的顺序来执行的,与他们在定义派生类构造函数中的次序无关。 { int xyz; public: Derived(int x1,int y1,int z1,int xyz1):Base(x1),Base1(x1,y1),Base2(x1,z1)//类之间构造函数的执行顺序与初始化表达式表中的顺序无关 { xyz=xyz1; cout<<"Constructing Derived"<<endl; } ~Derived() { cout<<"Destructing Derived"<<endl; } }; int main() { Derived ob(1,2,3,4);//Derived(1,2,3,4); system("pause"); }
在上例中,虚基类Base的构造函数只执行了一次。 这是因为当派生类Derived调用了虚基类Base的构造函数之后,类Base1和类Base2对虚基类Base构造函数的调用被忽略了。这是初始化虚基类和非虚基类的不同。
在使用虚基类时应注意如下几个问题:
1.虚基类的关键字virtual与派生方式的关键字private、protected和public的书写位置无关紧要,可以先写虚基类的关键字,也可以先写派生方式的关键字。
2.一个基类在作为某些类的虚基类的同时可以作为另一些类的非虚基类。
3.虚基类构造函数的参数必须由最新派生出来的类负责初始化,即使不是直接继承也应该如此。
例:
#include<iostream> using namespace std; class Base{ int x; public: Base(int y1) { x=y1; cout<<"Constructing Base, x= "<<x<<endl; } ~Base() { cout<<"Destructing Base"<<endl; } }; class Base0{ int x0; public: Base0(int y1) { x0=y1; cout<<"Constructing Base0, x0= "<<x0<<endl; } ~Base0() { cout<<"Destructing Base0"<<endl; } }; class Base1:virtual public Base { int y; public: Base1(int x1,int y1):Base(x1) { y=y1; cout<<"Constructing Base1, y= "<<y1<<endl; } ~Base1() { cout<<"Destructing Base1"<<endl; } }; class Base2: public Base0 { int z; public: Base2(int x1,int z1):Base0(x1) { z=z1; cout<<"Constructing Base2, z= "<<z<<endl; } ~Base2() { cout<<"Destructing Base2"<<endl; } }; class Derived: public Base2,public Base1,public Base0//基类之间构造函数的执行顺序是严格按照声明时从左到右的顺序来执行的,与他们在定义派生类构造函数中的次序无关。 { int xyz; public: Derived(int x1,int y1,int z1,int xyz1):Base(x1),Base0(x1),Base1(x1,y1),Base2(x1,z1)//类之间构造函数的执行顺序与初始化表达式表中的顺序无关 { xyz=xyz1; cout<<"Constructing Derived"<<endl; } ~Derived() { cout<<"Destructing Derived"<<endl; } }; int main() { Derived ob(1,2,3,4);//Derived(1,2,3,4); system("pause"); }