具有冲突方法的多重继承



我正在编写一些模板化的纯虚拟基类,这些基类是乘法继承的,并在此过程中发现了一个小的奇怪之处。关键是,如果您在两个基类中定义相同的方法,则从编译和工作正常继承,并且似乎只需要派生类中的单个定义。我很好奇这里幕后发生了什么,这是正确和有计划的行为还是危险的编译器疏忽?

有关说明性代码示例,请参见下文:

namespace
{
  template <typename T_NumType>
  class InheritFrom
  {
  public:
    virtual void doSomething(const T_NumType& numType) = 0;
    virtual void sharedMethod() = 0;
  }; // class
  class MultipleInheritor : public InheritFrom<int>, public InheritFrom<float>
  {
  public:
    void doSomething(const int& numType) {}
    void doSomething(const float& numType) {}
    void sharedMethod() {} // one definition here
  }; // class
}
int main(int argc, char** argv)
{
  MultipleInheritor mult;
  mult.doSomething(5);
  mult.sharedMethod();
}

编辑:
下面的答案和查看 C++98 标准终于为我澄清了这一点。

从 10.3 开始:虚拟函数:

在任何格式良好的类中,对于每个 其中声明的虚函数 类或其任何直接或间接 基类有一个独特的最终 覆盖该函数的覆盖器 以及所有其他覆盖者 功能。

因此,这意味着对于任何虚函数,都将找到一个最终覆盖器。这是通过 10.2:成员名称查找中详述的规则完成的。

因此,在我介绍的案例中,确实有两个基类函数,并且由于成员名称查找,派生类中的单个函数被确定为两者的最终覆盖器。因此,我所拥有的是完美的格式,并且是C++编译器工作的逻辑结果。

这些函数具有不同的签名(一个采用 int,一个采用浮点数),因此实际上并不"相同"。

模板魔术有点混淆了这一点,但它就像你有foo(int)foo(float)一样 - 这是两个不同的功能。你可以有foo(int) constfoo(int),这也是两个不同的功能。

编辑:好的,让我解决实际问题(如您的评论中所述)。从技术上讲,它仍然没有歧义:每个版本的InheritFrom都有自己的vtable,MultipleInheritor有一个vtable。您可以选择限定sharedMethod的任何父实现的范围(如 InheritFrom<int>::sharedMethod() ),但就调用方而言,类型 MultipleInheritor 的对象有一个 vtable,其中包含一个用于sharedMethod的条目。

编辑

编辑:关键是你在子类中实现了sharedMethod。如果它不是纯粹的并且没有MultipleInheritor实现,就会有一个编译器错误,因为不清楚在 vtable 中的一个插槽中放入什么。

在派生类中使用一个函数定义覆盖两个同名的虚函数是 C++ 中多重继承的一个特征。

Bjarne Stroustrup在这里描述了一种可能使用虚函数实现的MI:C++的多重继承

基本上,MultipleInheritorInheritFrom<int> vtable 和 InheritFrom<float> vtable 都会被修改,以便 sharedMethod 的两个条目都指向 MultipleInheritor::sharedMethod

最新更新