c++ 虚基类应用
多重继承存在二义性,为了消除二义性在访问相同名称的属性时需要加上类名,加以区分。虽然这样可以解决二义性,但是相同的属性出现在多个基类中,为了解决数据冗余,c++引入了虚基类。
虚基类定义:class 派生类名: virtual 继承方式 基类名
初始化
/* 如果在虚基类中定义了带参数的构造函数,而且没 有定义默认构造函数,则在其所有派生类(包括直 接派生或间接派生的派生类)中,通过构造函数的 初始化表对虚基类进行初始化。例如*/ class A//定义基类A {A(int i){ } //基类构造函数,有一个参数 …}; class B :virtual public A //A作为B的虚基类 {B(int n):A(n){ } //B类构造函数,在初始化表中对虚基类初始化 …}; class C :virtual public A //A作为C的虚基类 {C(int n):A(n){ } //C类构造函数,在初始化表中对虚基类初始化 …}; class D :public B,public C //类D的构造函数,在初始化表中对所有基类初始化 {D(int n):A(n),B(n),C(n){ } …}; /* 注意: 在定义类D的构造函数时,与以往使用的方法有所不同。规定: 在最后的派生类中不仅要负责对其直接基类进行初始化,还要负责对虚基类初始化。 C++编译系统只执行最后的派生类对虚基类的构造函数的调用,而忽略虚基类的其他派生类(如类B和类C) 对虚基类的构造函数的调用,这就保证了虚基类的数据成员不会被多次初始化。 */
应用实例:
#include "stdafx.h" #include <iostream> #include <string> using namespace std; //声明公共基类Person class Person { public: Person(string nam,char s,int a)//构造函数 { name=nam; sex=s; age=a; } protected: //保护成员 string name; char sex; int age; }; //声明Person的直接派生类Teacher class Teacher:virtual public Person //声明Person为公用继承的虚 { public: Teacher(string nam,char s,int a, string t):Person(nam,s,a)//构造函数 { title=t; } protected: //保护成员 string title; //职称 }; //声明Person的直接派生类Student class Student:virtual public Person //声明Person为公用继承的虚基类 { public: Student(string nam,char s,int a,float sco) //构造函数 :Person(nam,s,a),score(sco){ } //初始化列表 protected: //保护成员 float score; //成绩 }; //声明多重继承的派生类Graduate class Graduate:public Teacher,public Student //Teacher和Student为直接基类 { public: Graduate(string nam,char s,int a, string 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(int argc,char* argv[]) { Graduate grad1("Wang-li",'f',24,"assistant",89.5,1234.5); grad1.show(); return 0; } /* 不要提倡在程序中使用多重继承,只有在比较简单和不易出现二义性的情况或实在必要时才使用多重继承,能用单 一继承解决的问题就不要使用多重继承。也是由于这个原因,有些面向对象的程序设计语言(如Java,Smalltalk)并不支持多重继承。 */