4.6.3 虚基类
如果一个派生类的基类是从一个共同的基类派生出来的,那么派生类的对象就是底层基类的间接派生,它会出现多个基类的拷贝。程序中如何进行分辨呢?一种方法是利用作用域运算符,即在访问基类的成员时明确指出要访问的是哪一个基类的数据成员。另一种方法是利用虚基类。虚基类是让基类只有一个拷贝,程序中的访问就不会出现访问的不确定性。虚基类在派生类中声明,其格式为:
- class 派生类名:virtual 继承方式 基类
- {}
虚基类的声明与普通的继承形式相同,只不过要在继承方式的前面添加关键字:virtual。当使用虚基类时,基类只有一个拷贝,程序中的访问具有确定性。
【示例4.23】 下面给出虚基类的例子。
- #include"iostream.h"
- class base
- {
- public:
- base()
- {cout<<"基类base的构造函数"<<endl;}
- ~base()
- {cout<<"基类base的析构函数"<<endl;}
- };
- class A:virtual public base
- {
- public:
- A()
- {cout<<"基类A的构造函数"<<endl;}
- ~A()
- {cout<<"基类A的析构函数"<<endl;}
- };
- class B:virtual public base
- {
- public:
- B()
- {cout<<"基类B的构造函数"<<endl;}
- ~B()
- {cout<<"基类B的析构函数"<<endl;}
- };
- class C:public A,public B
- {
- public:
- C()
- {cout<<"派生类C的构造函数"<<endl;}
- ~C()
- {cout<<"派生类C的析构函数"<<endl;}
- };
- void main()
- {
- C p;
- }
程序运行结果如下:
- 基类base的构造函数
- 基类A的构造函数
- 基类B的构造函数
- 派生类C的构造函数
- 派生类C的析构函数
- 基类B的析构函数
- 基类A的析构函数
- 基类base的析构函数
这样程序对基类base只有一个拷贝,因此执行构造函数时,只要从基类base开始就可以了。如果未使用虚基类,那么程序的输出结果为:
- 基类base的构造函数
- 基类A的构造函数
- 基类base的构造函数
- 基类B的构造函数
- 派生类C的构造函数
- 派生类C的析构函数
- 基类B的析构函数
- 基类base的析构函数
- 基类A的析构函数
- 基类base的析构函数
此时类base有两个拷贝。当创建类C的对象时,需要逐层次的向前进行访问,出现基类base被构造两次。
警告:一个类由多个基类派生出来,则虚基类的构造函数先于非虚基类的构造函数的执行。
【责任编辑:
云霞 TEL:(010)68476606】