一、菱形继承的基本概念
菱形继承又称为钻石继承,由公共基类派生出多个中间子类,又由多个中间子类共同派生出汇聚子类。汇聚子类会得到,中间子类从公共基类继承下来的多份成员。
菱形继承的格式:
A --------公共基类
/ \
B C ------- 中间子类
\ /
D --------汇聚子类
示例:
#include <iostream>
using namespace std;
//封装公共基类 家具 类
class Jiaju
{
private:
string color;
public:
//无参构造
Jiaju() {cout << "家具的无参构造函数" << endl;}
//有参构造
Jiaju(string n):color(n)
{
cout << "家具的有参构造函数" << endl;
}
};
//中间子类
//封装 沙发的类
class Sofa:public Jiaju
{
private:
string sitting;
public:
//无参构造
Sofa() {cout << "沙发的无参构造" << endl;}
//有参构造函数
Sofa(string s,string c):Jiaju(c),sitting(s)
{
cout << "沙发的有参构造" << endl;
}
void display()
{
cout << sitting << endl;
}
};
//中间子类
//封装 床 类
class Bed:public Jiaju
{
private:
string sleep;
public:
//无参
Bed() {cout << "床的无参构造" << endl;}
//有参
Bed(string s,string c):Jiaju(c),sleep(s)
{
cout << "床的有参构造" << endl;
}
void display()
{
cout << sleep << endl;
}
};
//汇聚子类
//封装 沙发床类 继承于沙发 和 床
class Sofa_Bed:public Bed,public Sofa
{
private:
int w;
public:
//
Sofa_Bed(){cout << "沙发床的无参构造" << endl;}
//有参构造
Sofa_Bed(string sit, string s, int w,string c):Bed(s,c),Sofa(sit,c),w(w)
{
cout << "沙发床的有参构造" << endl;
}
};
int main()
{
// Sofa_Bed s;
Sofa_Bed s1("可坐","可躺",123,"pink");
return 0;
}
菱形继承存在的问题:
汇聚子类会得到,中间子类从公共基类继承下来的多份成员,造成空间浪费,没有必要,还会对公共基类的成员多次初始化,或释放。
二、虚继承
虚继承的作用:
可以让汇聚子类只保留一份 中间子类从公共基类继承下来的成员。
虚继承的格式:
在中间子类的继承方式前 加上 virtual
class 类名 : virtual 继承方式 类名 //中间子类
{
中间子类的拓展;
};
使用虚继承的注意事项:
中间子类虚继承公共基类后,汇聚子类的初始化列表,先调用中间子类的有参构造函数,中间子类再调用公共基类的有参构造函数。但是,虚继承之后,只保留一份中间子类从公共基类继承下来的有参构造函数,意味着不知道调用哪一个中间子类继承下来的公共基类的构造函数,这样就会默认调用公共基类的无参构造函数。
如果汇聚子类想要对公共基类的数据成员初始化,需要显性调用公共基类的构造函数。
示例:
#include <iostream>
using namespace std;
//封装公共基类 家具 类
class Jiaju
{
private:
string color;
public:
//无参构造
Jiaju() {cout << "家具的无参构造函数" << endl;}
//有参构造
Jiaju(string n):color(n)
{
cout << "家具的有参构造函数" << endl;
}
};
//中间子类
//封装 沙发的类
class Sofa:virtual public Jiaju //中间子类虚继承公共基类
{
private:
string sitting;
public:
//无参构造
Sofa() {cout << "沙发的无参构造" << endl;}
//有参构造函数
Sofa(string s,string c):Jiaju(c),sitting(s)
{
cout << "沙发的有参构造" << endl;
}
void display()
{
cout << sitting << endl;
}
};
//中间子类
//封装 床 类
class Bed:virtual public Jiaju //中间子类虚继承公共基类
{
private:
string sleep;
public:
//无参
Bed() {cout << "床的无参构造" << endl;}
//有参
Bed(string s,string c):Jiaju(c),sleep(s)
{
cout << "床的有参构造" << endl;
}
void display()
{
cout << sleep << endl;
}
};
//汇聚子类
//封装 沙发床类 继承于沙发 和 床
class Sofa_Bed:public Bed,public Sofa
{
private:
int w;
public:
//
Sofa_Bed(){cout << "沙发床的无参构造" << endl;}
//有参构造
Sofa_Bed(string sit, string s, int w,string c):Jiaju(c),Bed(s,c),Sofa(sit,c),w(w) //需要在汇聚子类中显性调用公共基类的有参构造函数
{
cout << "沙发床的有参构造" << endl;
}
};
int main()
{
// Sofa_Bed s;
Sofa_Bed s1("可坐","可躺",123,"pink");
return 0;
}