多重继承,C++;多个超类中的同一方法签名 我没有C++的经验,我来自java后台。最近,有人在采访中问我为什么Java不允许多重继承,答案很简单。但是,我仍然好奇C++是如何处理这个问题的,因为它允许你从一个以上的类继承。

多重继承,C++;多个超类中的同一方法签名 我没有C++的经验,我来自java后台。最近,有人在采访中问我为什么Java不允许多重继承,答案很简单。但是,我仍然好奇C++是如何处理这个问题的,因为它允许你从一个以上的类继承。,c++,inheritance,multiple-inheritance,C++,Inheritance,Multiple Inheritance,具体来说,假设有一个名为mechanicalenginer的类和另一个名为electricalenginer的类。两者都有一个名为buildRobot()的方法 如果我们制作一个第三类的机器人工程师,它从这两个类中继承而来,并且不重写该方法,您只需调用: (some instance of RoboticsEngineer).buildRobot() 将引发异常,还是将使用其中一个超类中的方法?如果是这样,编译器如何知道要使用哪个类?编译器会将这种情况(即,试图调用(RobotsenEngin

具体来说,假设有一个名为
mechanicalenginer
的类和另一个名为
electricalenginer
的类。两者都有一个名为
buildRobot()
的方法

如果我们制作一个第三类的
机器人工程师
,它从这两个类中继承而来,并且不重写该方法,您只需调用:

(some instance of RoboticsEngineer).buildRobot()

将引发异常,还是将使用其中一个超类中的方法?如果是这样,编译器如何知道要使用哪个类?

编译器会将这种情况(即,试图调用
(RobotsenEngineer.buildRobot()的某些实例)标记为错误

发生这种情况的原因是,派生对象在其内部有两个基本对象(一个
mechanicalenginer
实例和一个
electricalenginer
实例)的副本,并且仅方法签名不足以说明使用哪一个

如果在
robotisenginer
中重写
buildRobot
,则可以通过在类名前加前缀明确说明要使用哪个继承方法,例如:

void RoboticsEngineer::buildRobot() {
    ElectricalEngineer::buildRobot()
}
同样,您也可以通过在
buildRobot
前面加上类名来“强制”编译器使用一个或另一个版本:

 (some instance of RoboticsEngineer).ElectricalEngineer::buildRobot();
在这种情况下,将调用方法的
ElectricalEngineer
实现,没有歧义

MechanicalEngineer
ElectricalEngineer
都有
Engineer
基类,并且在这两种情况下都将继承指定为
virtual
时,会给出一种特殊情况。使用
virtual
时,派生对象不包含
Engineer
的两个实例,但编译器确保只有一个实例。这看起来像这样:

 class Engineer {
      void buildRobot();
 };

 class MechanicalEngineer: public virtual Engineer {

 };

 class ElectricalEngineer: public virtual Engineer {

 };
在这种情况下,

(some instance of RoboticsEngineer).buildRobot();

将毫不含糊地予以解决。如果buildRobot声明为
virtual
,并在两个派生类之一中重写,则情况也是如此。无论如何,如果两个派生类(ElectricalEngineer和MechanicalEngineer)都重写了
buildRobot
,则歧义再次出现,编译器将标记调用
(RobotsEngineer的某个实例)。buildRobot()作为错误。

它无法处理它。这是模棱两可的<代码>错误C2385:对“functionName”的访问不明确

编译器非常聪明,知道它不应该猜测您的意思。
对于要编译的程序,您需要告诉编译器:
答:你知道这是一个有问题的问题。
告诉它你的确切意思

要做到这一点,您需要显式地告诉编译器您要的是哪种方法:

RoboticsEngineer myRobot;
myRobot.ElectricalEngineer::buildRobot();

编译器会抱怨这种情况

<>在这种情况下,C++建议用一个“纯虚拟”方法构建BuoDeBoTo()函数来创建一个接口。MechanicaLenginer和EletriCalingInner将继承接口并重写buildRoboot()函数

创建RobotSengInner对象并调用buildRobot()函数时,将调用接口的函数

struct MecEngineer {

     void buildRobot() { /* .... */ }

};

struct EleEngineer {

     void buildRobot() { /* .... */ }

};

struct RoboticsEngineer : MecEngineer, EleEngineer {

};
现在当你这么做的时候

robEngObject -> buildRobot() ;
这样的调用无法解析,并且是不明确的,因为两个子对象都有一个具有相同签名的成员函数,而编译器不知道调用哪个。在这种情况下,您需要使用
操作符或使用
static\u cast
明确地提到它

static_cast<MecEngineer*> (robEngObject) -> buildRobot() ;
static_cast(robEngObject)->buildRobot();

关于多类继承,没有什么允许这样做。Java在接口方面也会产生同样的问题

public interface A {
    public void doStuff();
}
public interface B {
    public void doStuff();
}
public class C implements A, B {}

<> P>简单的答案是编译器在它上面投了一个错误。< /P>是C++,可以从两个以上的类继承吗?如果一个类有一个方法:“代码> BuffDooBoo.</代码>,一个接口有一个方法:代码> BuffDoBoo.<代码>,并且你定义一个子类,它也实现了接口?@ TOTO显然是很好的,只要java返回类型是相同的,请看这个。可以说虚拟与java中的关键字“implement”相同吗?@Yochai Timmer:你能更精确一点吗?在这两者中什么应该是虚拟的?继承还是方法?我做的任何陈述都有我做的编译器测试的支持@Kit Ho:我对Java了解不多,但既然
virtual
继承对于多重继承来说是有意义的,而且Java没有这些,我会怀疑它…@sergio:在编辑之前,你说过你只需要将这两种方法都虚拟化。你现在拥有的一切都会有用的。虽然OP问如果两个基类都有方法的实现会发生什么(问题不是钻石继承)@Yochai Timmer:我明白你的意思。在回顾了我的编辑之后,让我强调一下,这可能是我表达中的一个模棱两可的问题,因为我从来没有提到过将这些方法虚拟化;我说的是虚拟继承。我同意你的看法,我的回答中以“特殊情况”开头的部分不是严格要求的,只是为了完整性而给出的;第一部分是对问题的回答。谢谢你的评论!实际上,没有逻辑上的理由强制转换,因为使用范围运算符是足够的、更短的,并且在实践中通常更容易接受。在这种情况下,编译器为什么会抛出错误/将抛出什么错误?请记住,Java中的接口类似于纯虚拟函数。因此,C将需要实现该函数,调用它将不会导致歧义。