多个超类中的多重继承,C ++和相同方法签名

时间:2011-07-20 16:20:12

标签: c++ inheritance multiple-inheritance

我没有C ++经验,而且我来自Java背景。最近,我在接受采访时被问到为什么Java不允许多重继承,答案很简单。但是,我仍然很好奇C ++如何处理它,因为它允许你从多个类继承。

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

如果我们制作第三个班级RoboticsEngineer会发生什么,这两个班级从两者中都有,并且不会覆盖该方法,您只需致电:

(some instance of RoboticsEngineer).buildRobot()

是否会抛出异常,或者是否会使用其中一个超类的方法?如果是这样,编译器如何知道要使用哪个类?

5 个答案:

答案 0 :(得分:21)

编译器会将此类情况(即,尝试调用(some instance of RoboticsEngineer).buildRobot())标记为错误。

这是因为派生对象内部有两个基础对象(一个MechanicalEngineer实例和一个ElectricalEngineer实例)的副本,而单独的方法签名不足以告诉哪一个使用

如果您覆盖buildRobot中的RoboticsEngineer,则可以通过为类名添加前缀来明确说明要使用的继承方法,例如:

void RoboticsEngineer::buildRobot() {
    ElectricalEngineer::buildRobot()
}

通过相同的硬币,您实际上可以“强制”编译器使用buildRobot的一个版本或另一个版本,方法是在其前面添加类名:

 (some instance of RoboticsEngineer).ElectricalEngineer::buildRobot();

在这种情况下,将调用方法的ElectricalEngineer实现,没有歧义。

如果EngineerMechanicalEngineer都有ElectricalEngineer基类,并且在两种情况下都指定继承为virtual,则会给出一个特殊情况。使用virtual时,派生对象不包含两个Engineer实例,但编译器确保只有一个实例。 class Engineer { void buildRobot(); }; class MechanicalEngineer: public virtual Engineer { }; class ElectricalEngineer: public virtual Engineer { }; 。这看起来像这样:

(some instance of RoboticsEngineer).buildRobot();

在这种情况下,

virtual

将毫不含糊地解决。如果buildRobot声明为buildRobot并在两个派生类之一中重写,则情况也是如此。无论如何,如果两个派生类(ElectricalEngineer和MechanicalEngineer)都覆盖(some instance of RoboticsEngineer).buildRobot();,则会再次出现歧义,并且编译器会将调用{{1}}的尝试标记为错误。

答案 1 :(得分:5)

它没有处理它。这是模棱两可的。 error C2385: ambiguous access of 'functionName'

编译器很聪明,知道它不应该猜测你的意思 对于要编译的程序,您需要告诉编译器:
答:你知道这是一个有问题的问题 B.告诉它究竟是什么意思。

为此,您需要明确告诉编译器您要求的方法:

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

答案 2 :(得分:0)

编译器会抱怨这种情况。

在这种情况下,c ++建议使用“纯虚拟”方法buildRobot()函数创建一个接口。 MechanicalEngineer和EletricalEnginner将继承Interface并覆盖buildRoboot()函数。

当您创建RoboticsEnginner对象并调用buildRobot()函数时,将调用该接口的函数。

答案 3 :(得分:0)

struct MecEngineer {

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

};

struct EleEngineer {

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

};

struct RoboticsEngineer : MecEngineer, EleEngineer {

};

现在,当你这样做时,

robEngObject -> buildRobot() ;

这样的调用无法解决且不明确,因为两个子对象都具有相同签名的成员函数,并且编译器不知道要调用哪个。在这种情况下,您需要使用::运算符或使用static_cast明确提及它。

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

答案 4 :(得分:0)

没有任何关于允许这种情况的多类继承。 Java会产生与接口相同的问题。

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

简单的答案是编译器会抛出错误。