目录
三、例【5.9】在【例5.8】中在teacher类和student类之上增加一个共同的基类person,人员的一些基本数据放在person中
前言
从上面的例子可知,如果一个派生类有多个直接基类,而这些直接基类有有一个共同的基类,在派生类中会保留这个间接共同基类数据成员的多个同名成员。图5.19和图5.20描述了这种情况。在引用这些同名成员时,为避免二义性,必须在派生类对象名后增加直接基类名。如:
c1.A::a=3; c1.A::display();
一、虚基类的作用
如果不希望在派生类中保留间接共同基类的多个同名成员,C++提供了虚基类的方法,使派生类在继承间接共同基类时只保留一份成员。
虚基类:用于有共同基类的场合。
声明:以virtual修饰说明基类。(class B1:virtual public B)
作用:主要用来解决多层继承时可能发生的对同一基类继承多次而产生的二义性问题;为最底层的派生类提供唯一的基类成员,而不重复产生多次拷贝。
注意:在第一级继承时就要将共同基类设计为虚基类。
声明虚基类的格式:
class 派生类名:virtual 继承方式 基类名
当基类通过多条派生路径被一个派生类继承时,派生类只继承该基类一次。
现将A类声明为虚基类:
class A
{… … };
class B: virtual public A
{… … };
class C: virtual public A
{… … };
虚基类是在声明派生类时,指定继承方式时声明的。因为一个基类可以作为一个派生类的虚基类,同时也可以作为另一个派生类的非虚基类。
派生类B和C声明虚基类后,派生类D的成员如图5.23所示。
二、虚基类的初始化
如果在虚基类中定义了带参数的构造函数,而且没定义默认构造函数,要求在它的所有派生类(直接和间接)中,通过构造函数的初始化表对虚基类进行初始化。
class A
{ A (int k) { } … … };
class B: virtual public A
{B (int n ):A(n){ }… … };
class C: virtual public A
{C (int n ):A(n){ } … … };
class D: public B,public C
{D (int n ):A(n),B(n),C(n) { } … … };
【注】
在定义类D的构造函数时,与以往的方法不同。虚基类在派生类中只有一份数据成员,所以这份数据成员的初始化必须由派生类直接给出。如果不由最后的派生类(如图5.21的类D)直接对虚基类初始化,而由虚基类的直接派生类(如图5.21的类B和类C)对虚基类初始化,就有可能由于在类B和类C的构造函数中对虚基类给出不同的初始化参数。所以规定:最后的派生类不仅要负责对其直接基类初始化,还要负责对虚基类初始化。
可能有人提出:类D的构造函数用初始化表调用了虚基类的构造函数A,类B和类C的构造函数也用初始化表调用了虚基类的构造函数A,这岂不是调用了三次虚基类构造函数?其实C++编译系统只执行最后的派生类调用虚基类的构造函数,忽略虚基类其他派生类(如类B和类C)调用虚基类构造函数,保证对虚基类的数据成员只作一次初始化。
三、例【5.9】在【例5.8】中在teacher类和student类之上增加一个共同的基类person,人员的一些基本数据放在person中
#include <iostream>
#include <string.h>
using namespace std;
class Person
{
public:
Person(char *nam, char s, int a)
{ // 构造函数
strcpy(name, nam);
sex = s;
age = a;
}
protected: // 保护成员
char name[20];
char sex;
int age;
};
class Teacher: virtual public Person
{ //声明Person为公用继承的虚基类
public:
Teacher(char *nam, char s, int a, char *t): Person(nam, s, a)
{ //构造函数
strcpy(title, t);
}
protected: // 保护成员
char title[10]; // 职称
};
class Student: virtual public Person
//声明Person为公用继承的虚基类
{
public:
Student(char *nam, char s, int a, float sco):
Person(nam, s, a), score(sco) { } // 初始化表
protected: // 保护成员
float score; // 成绩
};
class Graduate: public Teacher, public Student
// 声明Teacher和Student类为公用继承的直接基类
{
public:
Graduate(char *nam, char s, int a, char *t, float sco, float w): // 构造函数
Person(nam, s, a), Teacher(nam, s, a, t), Student(nam, s, a, sco),
wage(w) {}
void show( )
{ // 输出研究生的有关数据
cout << "name:" << name << endl;
cout << "age:" << age << endl;
cout << "sex:" << sex << endl;
cout << "score:" << score << endl;
cout << "title:" << title << endl;
cout << "wages:" << wage << endl;
}
private:
float wage; //工资
};
int main( )
{
Graduate grad1("Wang-li", 'f', 24, "assistant", 89.5, 1234.5);
grad1.show( );
return 0;
}
四、多层多重继承用虚基类
#include <iostream&g