我正在编写一些模板化的纯虚拟基类,它们是多重继承的,并且在这个过程中发现了一个小小的奇怪现象。它的关键是,如果你在两个基类中定义相同的方法,继承两个编译并且工作正常,看起来你只需要派生类中的单个定义。我很好奇这里幕后发生了什么,这是正确的,有计划的行为还是危险的编译器疏忽?
请参阅下面的示例代码示例:
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 ++编译器工作的合理结果。
答案 0 :(得分:2)
这些函数有不同的签名(一个采用int,一个采用浮点数),因此实际上并不是“相同”。
模板魔术模糊了一点,但它与foo(int)
和foo(float)
相同 - 这是两个不同的功能。您可以拥有foo(int) const
和foo(int)
,这也是两个不同的功能。
编辑:好的,让我解决一下实际问题(如评论中所述)。从技术上讲,它仍然没有含糊不清:InheritFrom
的每个版本都有自己的vtable,MultipleInheritor
有一个vtable。您可以选择sharedMethod
的任何父实现的范围(如InheritFrom<int>::sharedMethod()
),但就调用者而言,类型为MultipleInheritor
的对象有一个vtable,其中一个条目为{{ 1}}。
编辑编辑:关键是你在子类中实现sharedMethod
。如果它不是纯粹的并且在sharedMethod
中没有实现,则会出现编译器错误,因为它不清楚将什么放入vtable中的一个插槽中。
答案 1 :(得分:1)
在派生类中用一个函数定义覆盖两个同名的虚函数是C ++中多重继承的一个特性。
Bjarne Stroustrup在此描述了使用虚拟函数实现MI的一种可能方式:Multiple Inheritance for C++
基本上InheritFrom<int>
vtable和InheritFrom<float>
vtable MultipleInheritor
会被修改,以便sharedMethod
的两个条目都指向MultipleInheritor::sharedMethod
。