多继承出现的菱形继承问题

问题:存在多继承特性的语言,在进行类的多继承时就会出现菱形继承的问题。

  1、菱形继承案例:

例如下述CPP代码:


c

代码解读

复制代码

class GrandParent_A { public: std::string a; GrandParent_A() { a = "GrandParent_A"; std::cout << "GrandParent_A Constructed" << std::endl; } //static void Print() //{ // std::cout << "is GrandParent_A Function" << std::endl; //} void Print() { std::cout << "is GrandParent_A Function" << std::endl; } virtual void PrintVirtual() { std::cout << "is GrandParent_A virtual Function" << std::endl; } virtual void PrintPureVirtual() = 0; }; class Parent_B :public GrandParent_A { public: std::string b; Parent_B() { b = "Parent_B"; std::cout << "Parent_B Constructed" << std::endl; } virtual void PrintVirtual() { std::cout << "is Parent_B virtual Function" << std::endl; } void PrintPureVirtual() override { std::cout << "is Parent_B Purevirtual Function" << std::endl; } }; class Parent_C :public GrandParent_A { public: std::string c; Parent_C() { c = "Parent_C"; std::cout << "Parent_C Constructed" << std::endl; } virtual void PrintVirtual() { std::cout << "is Parent_C virtual Function" << std::endl; } void PrintPureVirtual() override { std::cout << "is Parent_C Purevirtual Function" << std::endl; } }; class GrandSon_D :public Parent_B, public Parent_C { public: std::string d; GrandSon_D() { d = "GrandSon_D"; std::cout << "GrandSon_D Constructed" << std::endl; } //virtual void PrintVirtual() //{ // std::cout << "is GrandSon_D override Function" << std::endl; //} };

  类Parent_B,类Parent_C 分别继承类GrandParent_A,然后GrandSon_D同时继承了Parent_B,Parent_C。这就形成了菱形继承,这时候发现GrandParent_A会进行两次构造将内容复制两份。

  如下图,查看输出发现GrandParent_A进行了两次构造,

GrandParent_A进行了两次构造

再查看内存地址发现存在两个GrandParent_A字符串内容。

所以这是后想输出GrandParent_A的成员会出现 “不明确”警告。


c

代码解读

复制代码

GrandSon_D d; //std::cout << d.a << std::endl; //"GrandSon Da”不明确 std::cout << d.Parent_B::a << std::endl; std::cout << d.Parent_C::a << std::endl; //d.Print(); //"GrandSonD::Print"不明确 d.Parent_C::Print(); d.Parent_B::Print(); //d.PrintVirtual(); //"GrandSonD::PrintVirtual不明确 d.Parent_C::PrintVirtual(); d.Parent_B::PrintVirtual(); //d.PrintPureVirtual(); //"GrandSonD:PrintPureVirtual"不明确 d.Parent_C::PrintPureVirtual(); d.Parent_B::PrintPureVirtual();

2、使用虚继承解决菱形继承问题:

   对中间基类进行虚继承(继承时加上Virutal关键字),如下:


c

代码解读

复制代码

#pragma region 虚继承 class Parent_VirtualB : virtual public GrandParent_A { public: std::string b; Parent_VirtualB() { b = "Parent_VirtualB"; std::cout << "Parent_VirtualB Constructed" << std::endl; } //virtual void PrintVirtual() //{ // std::cout << "is Parent_VirtualB virtual Function" << std::endl; //} void PrintPureVirtual() override { std::cout << "is Parent_VirtualB Purevirtual Function" << std::endl; } }; class Parent_VirutalC :virtual public GrandParent_A { public: std::string c; Parent_VirutalC() { c = "Parent_VirutalC"; std::cout << "Parent_VirutalC Constructed" << std::endl; } //virtual void PrintVirtual() //{ // std::cout << "is Parent_VirutalC virtual Function" << std::endl; //} void PrintPureVirtual() override { std::cout << "is Parent_VirutalC Purevirtual Function" << std::endl; } }; class GranSon_VirtualD :public Parent_VirtualB, public Parent_VirutalC { public: std::string d; GranSon_VirtualD() { d = "GranSon_VirtualD"; std::cout << "GranSon_VirtualD Constructed" << std::endl; } void PrintPureVirtual() override { std::cout << "is GranSon_VirtualD Purevirtual Function" << std::endl; } }; #pragma endregion

  这时候就只会出现一次构造,内存里也只会有一份GrandParent_A内容,也避免了1里不明确的问题出现

3、为了避免多继承问题出现,要么多使用virtual,要么使用接口多实现来代替。


c

代码解读

复制代码

#pragma region 接口实现 class IGrandP_A { public: virtual void Print() = 0; IGrandP_A() { std::cout << "IGrandP_A Constructed" << std::endl; } }; class IParent_B :public IGrandP_A { public: //virtual void Print() = 0; virtual void Print() { std::cout << "is IParent_B function" << std::endl; } IParent_B() { std::cout << "IParent_B Constructed" << std::endl; } }; class IParent_C :public IGrandP_A { public: //virtual void Print() = 0; virtual void Print() { std::cout << "is IParent_C function" << std::endl; } IParent_C() { std::cout << "IParent_C Constructed" << std::endl; } }; class GrandSon_ID :public IParent_B, public IParent_C { public: void Print() { std::cout << "is GrandSon_ID function" << std::endl; } GrandSon_ID() { std::cout << "GrandSon_ID Constructed" << std::endl; } }; #pragma endregion

因为接口没有实现,子类实现是就属于子类了。而且没有字段。

其他没有多继承的语言如C#可能就是考虑到这个问题来,使用接口来避免。

参考链接:


arduino

代码解读

复制代码

https://zhuanlan.zhihu.com/p/365223471


arduino

代码解读

复制代码

https://zhuanlan.zhihu.com/p/342271992


arduino

代码解读

复制代码

https://zhuanlan.zhihu.com/p/651947545

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值