例必发365乐趣网投如变量的二义性

当前位置:必发365娱乐官方网站 > 必发365乐趣网投 > 例必发365乐趣网投如变量的二义性
作者: 必发365娱乐官方网站|来源: http://www.trans-bali.com|栏目:必发365乐趣网投

文章关键词:必发365娱乐官方网站,多重继承

  面向对象编程语言中的多重继承指的是一个类别可以同时从多于一个父类继承行为与特征的功能。与单一继承相对,单一继承指一个类别只可以继承自一个父类。重温Java,发现Java竟然不支持类多重继承(直接继承类),却允许接口的多重继承。。C++中类可以多重继承,Java中为什么不实现这个功能呢?多重继承会带来哪些问题,从而导致Java放弃类的多重继承?再一深究,发现多年以来,多重继承一直是个敏感话题,赞成者看到的是免去笨拙的混合继承的利处,反对者看到的是多处混淆的弊端,例如变量的二义性,并且是多个变量。所以关于它的好处与风险之间孰轻孰重成为OO界多年争论的焦点。其实最大的问题是出现拓补图,也就是出现钻石型继承结构(DOD),个人感觉这是个致命伤。正如其名:Diamond of Death。比如一个基类:动物。它有三个派生类:哺乳类动物,卡通类动物,宠物(确实都形成ISA关系)。现在有一个子类猫,从关系上推,它可以继承自哺乳类,卡通类,宠物,都符合ISA,如果要体现所有的特性,就需要全部继承,这样就形成了多重继承,却也形成了DOD,这样以后问题就出现了,从猫到动物的继承有三条路径,如果哺乳类,卡通类与宠物类中有相同的成员函数或变量,这样的数据组织方式会形成多义。C++怎么解决这个问题的呢?虚继承。结果就是不得不牺牲一些内存开销,因为一个功能要在多处被重写。并且函数表里的函数指针必须调整,必发365乐趣网投这样即使可以满足功能,在后期的维护也很复杂。并且,网上也有不少建议,要尽可能避免多重继承,不惜一切代价去避免钻石结构,以避免后期不可挽回的大返工。举个例子,交通工具类可以派生出汽车和船连个子类,但拥有汽车和船共同特性水陆两用汽车就必须继承来自汽车类与船类的共同属性。

  当一个派生类要使用多重继承的时候,必须在派生类名和冒号之后列出所有基类的类名,并用逗好分隔。

  上面的代码从表面看,看不出有明显的语法错误,但是它是不能够通过编译的。这有是为什么呢?

  在图中深红色标记出来的地方正是主要问题所在,水陆两用汽车类继承了来自Car类与Boat类的属性与方法,Car类与Boat类同为AmphibianCar类的基类,在内存分配上AmphibianCar获得了来自两个类的SetWeight()成员函数,当我们调用a.SetWeight(3)的时候计算机不知道如何选择分别属于两个基类的被重复拥有了的类成员函数SetWeight()。

  以上面的代码为例,我们要想让AmphibianCar类既获得一个Vehicle的拷贝,而且又同时共享用Car类与Boat类的数据成员与成员函数就必须通过C++所提供的虚拟继承技术来实现。

  我们在Car类和Boat类继承Vehicle类出,在前面加上virtual关键字就可以实现虚拟继承,使用虚拟继承后,当系统碰到多重继承的时候就会自动先加入一个Vehicle的拷贝,当再次请求一个Vehicle的拷贝的时候就会被忽略,保证继承类成员函数的唯一性。

  虽然说虚拟继承与虚函数有一定相似的地方,但读者务必要记住,他们之间是绝对没有任何联系的!

  1、当一个类有多个父类时,每个父类在内存中依次排列,然后该类自己的成员。

  3、当把子类的指针Upcast的时候,两种Upcast的方式得到的结果分别指向各自的父类镜像

  4、当两个父类重载的虚函数不同时,会使用Thunk机制,也就是说,虚函数表中的函数指针并不指向实际的虚函数,而是指向一小段代码。在这一小段代码中,会修改This指针(ECX寄存器),使之指向合适的父类镜像,然后再跳转到实际的虚函数体。

  5、当不使用虚继承时,共同基类的成员对象,在子类中会有独立两分(从两个父类各自继承了一份)。

  6、当使用虚继承时,共同基类的成员对象也会在虚函数表中记录,访问它必须先查找虚函数表。

  发表于 2008-10-28 20:27zml_cnnk阅读(5495)所属分类:C++ Tech

  name=评论 /

  即使是虛擬繼承,也很難解決多重繼承的二義性,因為即使解決了成員變量的二義性問題,為了產生多態效果的函數結構也會產生二義性,而且此時多態的函數之間是獨立的。

网友评论

我的2016年度评论盘点
还没有评论,快来抢沙发吧!