虚继承:在继承定义中包含了virtual关键字的继承关系;
虚基类:被虚继承的类,是相对概念;
例:people是student的虚基类
虚基类的出现时为了解决二义性问题,使派生类中只保留一份拷贝
经典菱形继承
student是people子类,teacher是people子类,doctor同时继承student和teacher
一般情况下,student和teacher中分别包含people的空间 ,doctor会直接继承两边people的空间,形成空间冗余
C++提供虚基类(virtual base class )的方法,使得在继承间接共同基类时只保留一份成员。
即在继承的同时加virtual 节省多余的空间,避免出现基类的多次继承
图解
①普通继承:
dortor的大小为(student属性)12+(teacher属性)12+(doctor属性)4=28
(保留两个people空间,出现空间冗余)
②生成一个student的虚基类:
dortor的大小为(student属性)12+(student的虚基类指针)4+(teacher属性)12+(doctor属性)4=32
③虚基类:
dortor的大小为(student属性)12+(student的虚基类指针)4+(teacher属性)12+(teacher的虚基类指针)4+(doctor属性)4-(people属性)8=28
声明方式
关键字 virtual
一般形式为
class 派生类名:virtual 继承方式 基类名
经过这样的声明后,当基类通过多条派生路径被一个派生类继承时,该派生类只继承该基类一次。
如果基类的全部派生类没有都使用虚基类的话,还是会出现多次继承。
代码实现
简易版abcd
#include<iostream>
using namespace std;
class A
{
protected:
A(int q):a(q){}
int a;
};
class B:virtual protected A
{
protected:
B(int w,int a):b(w),A(a){}
int b;
};
class C:virtual protected A
{
protected:
C(int e,int a):c(e),A(a){}
int c;
};
class D:protected B,protected C
{
protected:
int d;
public:
D(int q,int w,int e,int r):A(q),B(w,0),C(e,0),d(r){}
void showd()
{
cout<<a<<endl;
cout<<b<<endl;
cout<<c<<endl;
cout<<d<<endl;
}
};
int main()
{
D d(1,2,3,4);
d.showd();
return 0;
}
人类学生老师版
#include<iostream>
using namespace std;
//people
class people
{
public:
people()
{
name="\0";
id=0;
}
people(string n,int i):name(n),id(i)
{
}
void show()
{
cout<<name<<" "<<id<<" "<<endl;
}
protected:
string name;
int id;
};
//student
class student:virtual public people
{
public:
student(string n,int i,int s):people(n,i),score(s)
{
}
void shows()
{
//show();
cout<<score<<" "<<endl;
}
protected:
int score;
};
//teacher
class teacher:virtual public people
{
public:
teacher(string n,int i,int g):people(n,i),grade(g)
{
}
void showt()
{
//show();
cout<<grade<<" "<<endl;
}
protected:
int grade;
};
//docter
class doctor:public student,public teacher
{
public:
doctor(string n,int i,int s,int g,string sch):people(n,i),student("",0,s),teacher("",0,g),school(sch)
{
}
void showd()
{
show();
shows();
showt();
cout<<school<<" "<<endl;
}
protected:
string school;
};
//main
int main()
{
doctor d("lc",1001,100,17,"sy");
d.showd();
cout<<sizeof(people)<<endl;
cout<<sizeof(student)<<endl;
cout<<sizeof(teacher)<<endl;
cout<<sizeof(doctor)<<endl;
return 0;
}
代码输出为
lc 1001
100
17
sy
8
16
16
28