VB和JAVA都不支持多重继承,为什么啊?为啥C++支持多重继承?它们是出于什么考虑?

解决方案 »

  1.   

    可能 Java 和 VB 都致力于“简单易用”,而如果多重继承的话,那真的不会太简单。
      

  2.   

    Java 可不是致力于“简单易用”而且虽然java不支持多重继承但Java用接口可以实现多重继承
      

  3.   

    照sun的讲法是避免c++那样管理多重继承的层次关系而带来的复杂性,换成用接口来实现多重继承的大部分功能。
      

  4.   

    接口类啊~~~interface, implement...用这个代替多继承的。
    再说, 一般很少会用到这个多继承的吧?
      

  5.   

    VB6根本不支持类继承。但是支持接口继承。
    多重继承的滥用会导致一些副作用,最典型的是菱形继承的二义性问题,比如:
    class B 和 class C 从 class A 继承。class D 从 class B 和 Class C 继承。那么 class D 访问 class A 的成员的时候,就有两条路径。当 class B 和 class C 各自覆盖了这个成员,那么到底应该调用哪个成员呢?就出现了二义性。
      

  6.   


    照你这么说,其实VB也支持“多重继承”了,因为VB也可以多重implements接口的。
      

  7.   


    其实有一点我一直很晕,也许应该另开一个帖子来讨论,又或者在这个帖子里讨论更合适:http://topic.csdn.net/u/20090630/22/c80bdb35-6eaf-4791-bdcf-27a00057d739.html就是,在形式上,我觉得类继承和接口继承非常相像。既然有类继承,嘛还发明一个接口继承呢?看到有一种说法是,继承是子类用父类的方法,多态(也就是接口继承吧?)是父类用子类的方法。我猜这两者在使用上一定有某种互补性,满足代码重用的不同方面。不然何必多设计一个特性?但是没有找到说得很清楚的解释……
      

  8.   

    高手朋友们都很低调,我把收到的私信发在这里和大家分享讨论,ID就暂时褒蜜了:) 并不点名地严重感谢。回复1:我觉得最重要的原因就是为了简单。 如果继承自两个类,而这两个类有同名方法的时候,子类如果不重载这个方法,当你调用这个子类的方法时,应该哪个父类的方法生效呢? 回复2:
    多继承这个东西,不管是理论上,还是实际项目中,都是需要的。但它有两方面的问题,一方面,虽然需要,但需要的情况不多;另一方面,实现起来又有些麻烦,比如指针类型转换时需要做偏移。于是就产生了一个问题:克服很多麻烦去实现一个使用得并不多的东西,到底值不值得。VB和JAVA选择了不实现它,C++则选择了实现它。但JAVA做了很多折衷:比如允许实现多个接口,还允许类的内部类再继承别的类。 COM是支持多继承的,COM实现中不允许使用的是虚拟继承。因为虚拟继承在不同的编译器中的实现方式很不相同,甚至同一编译器的不同版本实现起来都可能有不同。而非虚拟的继承在大多数编译器中的实现方式都类似。 
      

  9.   

    直接的继承VB确实不支持,但可以通过其他的方法模仿出继承和派生类的效果,
    就是过程没有C那么方便,大致方法有点像封壳。比如:如果想继承一个类的所有属性和方法和事件,那么可以先引用该类并在你的类中创建该对象。
    然后然后将其所有的属性、事件、方法的读写属性过程、事件产生及方法调用的过程都在你的类中进
    行调用和传递,然后还可以添加自己的属性、方法、事件,这样的效果就很像继承后派生出来的类了。
    虽然方法比较麻烦,但可以做到类似的效果。
    至于为什么VB不直接支持继承,那只有Microsoft才知道,别人瞎猜不论猜对猜错都没多大意义,因
    为根本就不知道标准答案。其实在程序中技术和想法的实现,不一定完全靠开发工具本身所提供的,就VB来说,提供基本的语句、
    函数、对象...,其语句和函数的功能其实并不怎么样,但如果调用外部的API和使用第三方开发的控
    件、组件等东西,那就可以做出很多很NB的东西。所以,我认为能达到目的就好,至于过程可以选择简单方便的东西,也可以选择自己熟悉的东西,反正
    接口也那么多种,即使VB不支持继承,那用别的东西开发然后给VB调用也是可以的,反正VB就是专门调
    用东西过活的,这样才能显得VB的“开发效率高”嘛,呵呵。
      

  10.   

    其实吧,从设计上说,继承已经是不需要的了,而且要尽量避免。
    过几年,C++标准成熟后,都不需要有继承了。实现继承->用包含代替
    接口继承->用Concept代替至于C++里的多重继承,是很常用的,ATL/WTL库里遍地都是。
      

  11.   

    补充一点,16楼所说的虚拟继承是指C++里这样的: class A : public virtual B { ... } 
      

  12.   

    这种说法我也看到过,不过却忘了是为啥了?这个说的是17楼的用法么?concept的话不懂是在说啥。不过的话,你这样划分继承,倒好像叫我明白在14楼的问题了。多态是接口继承,而类继承是实现继承,它们在这个意义上互补。但可能还可以有更本质的解释,期待中……
      

  13.   


    回复1:我觉得最重要的原因就是为了简单。 如果继承自两个类,而这两个类有同名方法的时候,子类如果不重载这个方法,当你调用这个子类的方法时,应该哪个父类的方法生效呢?----------------------------
    好像记得Java核心技术一书中提到了不支持多继承是为了关系简单,但又记不太清了。回复2:
    多继承这个东西,不管是理论上,还是实际项目中,都是需要的。但它有两方面的问题,一方面,虽然需要,但需要的情况不多;
    --------------------------------------------------------------
    第一个方面感觉符合降低耦合和高聚合的设计模式说法。
      

  14.   

    开发复杂度: 多重继承 < 单继承
    维护复杂度: 多重继承 > 单继承
      

  15.   

    继承是非常强的耦合,自然是要避免的是的,包含实现类,然后传递方法调用。继承的目的就是两个:代码重用和满足接口。
    为了代码重用去引入一个强耦合就很没必要了,所以最好用包含代替。
    接口继承是一个弱耦合,语法上的。C++里其实没有接口的概念,是用抽象基类模拟的。
    接口继承在C++的模板类里是不需要的,C++模板支持静态的Ducking Type,
    只要满足Concept(概念,约束,可以理解为一种对接口的描述吧),就可以用,
    语法上不需要继承接口。
    不过动态多态还是要用到接口继承的。我说的是C++里的,可能不能完全套用在其他语言上,不过概念上应该差不多吧。
      

  16.   

    concept你会不会拼错了,实际上是contract?
      

  17.   


    不是,我说的Concept是C++里的概念,是对类型的约束。
    你说的Contract是指基于契约的设计DBC。
      

  18.   

    术语定义的问题导致表达和理解的不一致,尽量统一一下:·(纯粹的)继承
    大家都明白的对象关系,可是由于学习不同的编程语言,有不同的判定标准,所以请尽量不要直接用这个描述问题。·类的继承
    C++ 为代表,一句简单的语句就使得子类自动拥有了父类的成员以及成员的具体实现。
    对应现实中血缘继承的生物特征。·接口的继承
    COM/VB 为代表,类必须实现接口的成员,类之间的同名成员实现没有必然的直接关系。
    对象现实中职务继承的职责和权限。·虚拟继承
      

  19.   


    确实有相似之处,而且从逻辑功能上分析,类继承也常常隐含着接口继承。
    在JAVA中,“接口”(interface)不再仅仅是个抽象的概念,而且成了一个语法实体。所以在JAVA中讨论“接口继承”要明确说明语境,你指的是两个interface之间的extends呢?还是仅仅从一般面向对象理论的角度,来分析父类与子类之间的接口一致性呢?这个说清楚了,也就不会有什么歧义了。
    另外,从理论角度来说,还有一种“实现继承”,在C++语言中一般通过private继承来实现。这种继承的含义是:子类只是想借用父类的一些功能来实现自身(代码复用),而并不像“接口继承”那样为了声明跟父类相通的功能接口。在C++的“private继承”中,子类继承父类这件事是个“秘密”,所以非常适合构造“实现继承”。
    此外,JAVA中不支持多继承,却允许一个类实现多个接口。除了逻辑功能上的考虑之外,还有语言实现方面的原因。实现JAVA编译器的时候,当遇到把一个对象向上转型为它所实现的任何一个接口类型时,内部的对象指针都不需要做偏移调整,因为接口都是没有实例成员的,也就是说,接口在对象中占的“size”都是0。而C++支持多继承,就不一样了,指针向上转型的时候,如果有多个父类,常常需要做偏移调整。
      

  20.   

    to ahao:内啥,我咋没觉得包含比继承的耦合弱啊?
      

  21.   

    补充一下:虚拟继承是C++中的一种实现继承的方法,一般用来处理多重继承里菱形继承二义性。http://school.cnd8.com/c/jiaocheng/8505.htm
      

  22.   


    这个耦合是指类的使用者和类之间的耦合,不是指内部细节。我就说c++好了,公有继承关系是公开的,暴露了实现细节,假设B从A继承,使用者会依赖于“B也是一个A”这样一个实现细节,可能会拿着B当成A到处使用(因为这种用法是推荐的,子类替换原则)。
    但哪天你觉得A的实现不好,要换个实现怎么办呢?只能改成从C继承,这样,就完全打破使用者的假设。而包含关系是内部细节。
    哪天你换个内部细节实现类都没关系,因为接口,继承关系都没变化。
    也就是和外部完全没有耦合。所以,如果只是为了代码重用,尽量避免继承的方式。不过我不清楚VB里是否是类似的。
      

  23.   

    其实包含关系就是COM使用的代码重用方式(包含和聚合),关键就是要隐藏具体实现。
      

  24.   

    UP。
    在C++里,除了友元,没有比继承耦合性更强的东西了。
    当客户代码把Derived当成一种Base之后,以后若想“脱离父子关系”,代价会很高。包含则没有这种事情。另外,私有继承也可以。在私有继承中,客户代码无法把Derived当然一种Base。
      

  25.   

    明白了,谢谢ahao和晨星。记得最早看的OOP书好像是以borland C++做例子的,讲得很清楚,可惜找不到了。看你们这么一说,是不是其实C++是支持OO思想最彻底的语言?比如有些精细的概念在其他语言中就不存在,比如继承的话,VB6里可没这么多种继承,也就一个接口继承勉强可以叫继承。
      

  26.   

    判断A模块和B模块是否耦合,就是要想一想,如果A模块的实现变化了,B模块会受多大的影响,对吧?如果按这种标准来判断耦合,那COM是很好的标准啊。因为它要求接口永远不变,甭管实现变多少,调用COM组件的客户端程序都不受影响,因此都不跟它耦合。
      

  27.   

    java、C++都不是很彻底,java相对彻底点儿!
      

  28.   


    OOP最彻底应该算不上,只能说,C++的控制力最强,程序员可以微调各个方面,但这样也造成复杂度的提高。
    判断耦合很简单的,就是知道的东西越少越好。不知道就没有耦合了。
    B不知道A的具体实现,自然就不会和他的实现耦合,否则A的实现一变化就会影响B。COM设计的原则就是接口和实现解耦,和编译器解耦,和语言解耦。
    所以COM组件的重用性高。
      

  29.   

    为什么需要接口继承。接口继承的意义在于,为一组相关的类提供一个统一的约定。也就是说,支持这个接口的类必然实现了接口约定的方法。接口类似硬件上的总线规范。在Java里面,类继承被叫做child继承parentclass,而接口继承叫做child实现interface。现代的OO设计强调使用接口继承和聚合代替类继承,面向接口而不是实现编程。然而,使用接口也有副作用,比如为了向前兼容组件,那些已经废弃的接口仍然需要实现。比如IE的COM接口,你会看到IWebBrowser、IWebBrowser2……所以接口的设计要格外谨慎,每个开放的方法都要仔细推敲。
      

  30.   

    结帖了。这个帖子讨论得比较深入也有点跑题,把对我有启发的回复放在这两个博文里:http://blog.csdn.net/slowgrace/archive/2009/07/02/4316003.aspxhttp://blog.csdn.net/slowgrace/archive/2009/07/03/4318345.aspx只是摘录,并未小结,图个日后查阅方便。没小结的原因是功力不够,如果勉强形成结论可能也没啥意义。感谢楼上各位的指教,尤其感谢ahao和晨星的深度参与。
    ----
    给新版CSDN的建议