虚基类
定义
定义派生类时,在积累继承方式前加关键字virtual,那么该基类就成为虚基类。
间接基类、直接基类
关系如下
//间接基类A
class A{
protected:
int m_a;
};//直接基类B
class B: virtual public A{ //虚继承
protected:
int m_b;
};//直接基类C
class C: virtual public A{ //虚继承
protected:
int m_c;
};//派生类D
class D: public B, public C{
};
作用
经过这样的声明后,当基类通过多条派生路径被一个派生类继承时,该派生类只继承基类一次。所以,为保证虚基类在派生类中只继承一次,应该在所有直接派生类中声明该基类为虚基类。
初始化
建立派生类对象是,对虚基类数据成员的初始化也是在派生类构造函数的初始化列表中进行的。在调用优先级上,虚基类构造函数的调用优先于非虚基类构造函数。
要指出的是:如果没有显性列出(在派生类构造函数右边不写入任何基类信息时),意味着虚基类没有定义带参数的构造函数,这时要调用的是虚基类默认构造函数。若在虚基类中仅编写带参数的构造函数,这时候会报错(自己写构造函数时,编辑器就不会构造其默认构造函数)。具体例子如下:
解决方法:
①构造基类的无参数构造函数;
②在派生类构造函数中显性列出对虚基类数据成员的初始化。
不过在创建派生类对象时,程序只调用其他中间虚基类的构造函数一次,而且是在调用该派生类构造函数时发生的,在调用其他中间派生类构造函数时不再调用虚基类的构造函数,从而保证虚基类的对象只被创建一次,其数据成员只被初始化一次。
虚继承
定义:让某个类做出声明,承诺愿意共享它的基类并在间接继承共同基类时只保留一份基类成员。其中,这个被共享的基类被称为虚基类。
在这种机制下,不论虚基类在继承体系中出现了多少次,在派生类中都只包含一份虚基类的成员。下图当定义 D 类(菱形继承)时才出现了对虚派生的需求。
包含引用