菱形继承

原创 2016年08月28日 16:11:13

多继承的好坏

相对java的单一继承,cpp、python允许多继承,尤其是python还完全支持菱形继承。
这一特性,使得类继承关系变得复杂,很容易出现问题,比如菱形继承下的函数虚函数的调用混淆的问题(下面会说到)。实际开发时,很多团队也是通过文档硬性规定为单继承加自定义接口(纯虚类)。
不过也有人认为,一个语言的不应该因为一些新手常犯的问题而硬性规定、限制某些特性,比如多继承,而且cpp本身就不是面向新手的。决不决定使用多继承应该有程序员本身决定,而不应该由语言本身限定,你可以不用,但我不能没有。
这一论战属于语言设计思想层面,也没有绝对的对错。

cpp多继承

总结来说cpp在语法上是可以使用菱形继承的,但是菱形继承创建的对象无法使用多态

class A{ 
public:
    virtual void func(){ cout << "A" << endl;}
}

class B : public A{
public:
    virtual void func(){ cout << "B" << endl;}
}

class C: public A{    
public:
    virtual void func(){cout << "C" <<endl;}
}

class D: public B, C{
public:
    virtual void func(){cout << "D" <<endl;}
}

int main(){
    D d;                    // 没有问题
    d.func();             // 如果D没有重写func,会编译报错
    A* a = new D(); // 编译报错,无法使用多态
    return 0;
}

对于上面的例子,如果D没有重写func函数,后面d.func会由于不知道调用B的func还是C的func而报错。
同样的道理,在使用多态时,不知道创建一个A*指向D时,不知道使用那条继承链。


python多继承

但是python里的菱形继承却不会编译报错,经过测试对于class D(B, C),如果出现调用或继承链的混淆,那么默认选用最一个符合的的。
比如d.func(),在cpp中由于B和C都实现了func,所以出现了调用混淆。继承时(B,C),B在C前面,所以使用B.func()
由于python是动态弱类型语言,不存在cpp里面A*的问题。

#coding=utf-8
class A: # 默认继承object
    def func(self):
        print "A"

class B(A):
    def func(self):
        print "B"

class C(A):
    def func(self):
        print "C"

class D(B, C):
    pass

d = D()
print isinstance(d, D), isinstance(d, A), isinstance(d, B), isinstance(d, C), isinstance(d, object)
d.func()

菱形继承引发的问题和解决方案,以及底层实现的原理.

定义:两个子类继承同一个父类,而又有子类同时继承这两个子类。          如果直接继承会引发访问不明确(二义性),以及数据冗余。如果直接指定访问对象,可解决二义性(第一段代码以及解析图),而要解...
  • zhu_931
  • zhu_931
  • 2017年03月26日 16:38
  • 478

菱形继承

多继承的好坏相对java的单一继承,cpp、python允许多继承,尤其是python还完全支持菱形继承。 这一特性,使得类继承关系变得复杂,很容易出现问题,比如菱形继承下的函数虚函数的调用混淆的问...
  • yinglang19941010
  • yinglang19941010
  • 2016年08月28日 16:11
  • 519

Java继承个人的理解

企鹅类:public class Penguin { private String name; private int id; public Penguin(Str...
  • mypython1
  • mypython1
  • 2017年10月07日 18:51
  • 56

菱形继承与菱形虚拟继承

“菱形继承与菱形虚拟继承”             “继承”是c++面向对象语言的特点之一,对于一个类,我们如果想对这个类的功能进行扩充,这就可以通过"继承"的方式重新增添或删除这个类中的某些功能。C...
  • ttyue_123
  • ttyue_123
  • 2016年08月09日 21:42
  • 288

【C++基础之二十一】菱形继承和虚继承

菱形继承是多重继承中跑不掉的,Java拿掉了多重继承,辅之于接口。C++中虽然没有明确说明接口这种东西,但是只有纯虚函数的类可以看作Java中的接口。在多重继承中建议使用“接口”,来避免多重继承中可能...
  • jackyvincefu
  • jackyvincefu
  • 2014年01月05日 09:05
  • 10539

菱形继承的内存布局是怎么回事呢?访问时,又会出现什么情况?

首先,我们看一下菱形继承(也叫钻石继承)的类之间的关系,如下图: 这样的话,那D类有两个B类成员吗?,访问的话岂不是两个同名吗?那我们验证一下, 用代码表示的话就是://菱形继承 #inclu...
  • lizhidefengzi
  • lizhidefengzi
  • 2017年02月25日 21:05
  • 386

python——继承介绍以及单继承

1、继承的概念    在程序中,继承描述的是事物之间的所属关系。比如说猫和狗都属于动物,那么猫和狗这两个类就可以继承动物这个类的一些属性和行为。其中,猫狗称为子类,动物称为父类。2、Demo    #...
  • wemozj
  • wemozj
  • 2018年02月14日 14:22
  • 4

java接口菱形继承

其实菱形继承的副作用只是因为公共基类的成员变量 Java的接口可以做出类似菱形继承的结构,但因为公共基类(接口?)中没有成员变量,所以没有二义性问题啦 当然也可以使用内部类(嵌套类)来实现类似...
  • wenwenxiong
  • wenwenxiong
  • 2015年04月30日 18:32
  • 972

C++菱形继承与虚继承

虚继承,菱形继承
  • xiaolewennofollow
  • xiaolewennofollow
  • 2016年08月14日 12:20
  • 805

C++(笔记)浅析菱形继承&虚继承底层内存占用

一、什么是菱形继承二、代码实现#include   #include   #include   #include #include #include #include using namesp...
  • w_linux
  • w_linux
  • 2017年05月04日 11:09
  • 526
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:菱形继承
举报原因:
原因补充:

(最多只允许输入30个字)