[英]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
实现,没有歧义。
当您同时拥有MechanicalEngineer
和ElectricalEngineer
的Engineer
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.