繁体   English   中英

多个超类中的多个 Inheritance、C++ 和相同的方法签名

[英]Multiple Inheritance, C++ and Same Method Signature in Multiple Super Classes

我没有 C++ 的经验,我来自 Java 背景。 最近,我在一次采访中被问到为什么 Java 不允许多重继承,答案很简单。 但是,我仍然对 C++ 如何处理这个问题感到好奇,因为它允许您从多个 class 继承。

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

如果我们制作第三个 class RoboticsEngineer会发生什么,它继承自两者并且不覆盖该方法,您只需调用:

(some instance of RoboticsEngineer).buildRobot()

是否会引发异常,或者将使用来自超类之一的方法? 如果是这样,编译器如何知道要使用哪个 class?

编译器会将这种情况(即尝试调用(some instance of RoboticsEngineer).buildRobot()为错误。

发生这种情况是因为派生的 object 在其内部拥有两个基础对象(一个MechanicalEngineer实例和一个ElectricalEngineer实例)的副本,并且仅方法签名不足以判断使用哪一个。

如果您在RoboticsEngineer中覆盖buildRobot ,您将能够通过为 class 名称添加前缀来明确说明要使用的继承方法,例如:

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

同样,您实际上可以通过在 class 名称前加前缀来“强制”编译器使用buildRobot的一个或另一个版本:

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

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

当您同时拥有MechanicalEngineerElectricalEngineerEngineer base class 并且您指定 inheritance 在这两种情况下都是virtual的时,会给出一个特殊情况。 使用virtual时,派生的 object 不包含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 ,那么歧义再次出现,编译器将标记调用尝试(some instance of RoboticsEngineer).buildRobot(); 作为一个错误。

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

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

为此,您需要明确告诉编译器您要使用哪种方法:

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

编译器会抱怨这种情况。

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

当您创建 RoboticsEngine object 并调用 buildRobot() function 时,将调用接口的 function。

struct MecEngineer {

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

};

struct EleEngineer {

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

};

struct RoboticsEngineer : MecEngineer, EleEngineer {

};

现在当你这样做时,

robEngObject -> buildRobot() ;

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

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

没有多个 class inheritance 允许这样做。 Java 对接口产生同样的问题。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM