虚基类的概念:
若在多继承派生类中继承的基类再拥有一个公共基类,则这个公共基类会在多继承派生类的对象中产生多个公共基类子对象,如果要使这个公共基类再多继承派生类中只产生一个基类子对象,则需要将这个基类设置为虚拟基类,简称虚基类。
引进虚基类的目的是为了解决二义性问题,使得公共基类再它的派生类对象中只产生一个基类子对象。
虚基类说明格式为:
virtual <继承方式> <基类名>
virtual是说明虚基类的关键字,虚基类说明用在定义派生类时,卸载派生类名的后面。
分析下面的程序:
<span style="font-size:18px;">class A//多继承派生类D的虚基类 { public: void f(); private: int a; }; class B:virtual class A { protected: int b; }; class C:virtual class A { protected: int c; }; class D:public class B,public class C//多继承派生类D { public: int g(); private: int d; };</span>
程序分析:
1,定义一个派生类D的对象d,则d.f(); 的形式是合法的。
2,定义void D::g()
{ f(); } 也是合法的。
3,定义A *pd ; pd=&d; 也是合法的。
引进虚基类后,派生类中只存在一个虚基类的子对象。当一个类有虚基类时,编译系统将为该类的对象生成一个指向虚基类的子对象的指针,该指针称为虚基类指针。
虚基类及派生类的构造函数
C++语言规定,虚基类子对象是由最远派生类的构造函数通过调用虚基类的构造函数进行初始化的。最远派生类是指在多层次的继承结构中,创建对象所指定的类。如果一个派生类有一个直接或间接的虚基类,则派生类的构造函数的成员初始化列表中必须包含对虚基类构造函数的调用。如果未列出,则表示该虚基类的默认构造函数来初始化派生类派生类对象中的虚基类子对象。为了保证虚基类子对象只被初始化一次,规定在创建对象的最远派生类的构造函数中调用虚基类的构造函数,而该派生类的基类构造函数中忽略对虚基类构造函数的调用。
C++语言有规定,在派生类构造函数的成员初始化列表中,出现虚基类构造函数先于非基类构造函数的调用。
<span style="font-size:18px;">#include <iostream> using namespace std; class A { public: A(const char *s) { cout<<s<<endl; } }; class B:virtual public A { public: B(const char *s1,const char *s2):A(s1) { cout<<s2<<endl; } }; class C:virtual public A { public: C(const char *s1,const char *s2):A(s1) { cout<<s2<<endl; } }; class D:public B,public C { public: D(const char *s1,const char *s2,const char *s3, const char *s4):B(s1,s2),C(s1,s3),A(s1)//多继承派生类D的构造函数 { cout<<s4<<endl; } }; int main() { D *ptr=new D("class A","class B","class C","class D");//多继承派生D的对象 delete ptr; return 0; }</span>
程序分析:在派生类B和C中使用了虚基类A,使得派生类D的对象中只有一个基类A的子对象。输出的结果为:class A class B class C class D