多重继承:2类1方法

Multiple inheritance: 2Classes1Method

本文关键字:1方法 2类 多重继承      更新时间:2023-10-16

我刚刚尝试了这段代码:

struct FaceOfPast
{
    virtual void Smile() = 0;
};
struct FaceOfFuture
{
    virtual void Smile() = 0;
};
struct Janus : public FaceOfPast, public FaceOfFuture
{
    virtual void Smile() {printf(":) ");}
};

void main()
{
    Janus* j = new Janus();
    FaceOfFuture* future = j;
    FaceOfPast* past = j;
    future->Smile();
    past->Smile();
    delete j;
}

按预期工作(输出两个笑脸),但我认为它甚至不应该编译,重新声明Smile() Janus模棱两可。

它是如何(以及为什么)工作的?

没有歧义,因为您在指向FaceOfFuture的指针上调用Smile(),并且FaceOfPast只声明一个方法Smile()

由于在基类指针上调用该方法

不会导致歧义,因此让我们处理直接在子类指针上调用该方法时的情况

Janus* j = new Janus();
j->Smile();

派生类除了重写之外,还隐藏了基类的Smile()声明。仅当您不会重写派生类中的方法时,才会有歧义:

以下编译:

struct FaceOfPast
{
    virtual void Smile() {printf(":) ");}
};
struct FaceOfFuture
{
    virtual void Smile() {printf(":) ");}
};
struct Janus : public FaceOfPast, public FaceOfFuture
{
   virtual void Smile() {printf(":) ");}
};
int main()
{
   Janus* j = new Janus();
   j->Smile();
}

尽管在Janus上调用Smile,但基类声明是隐藏的。

以下不会:

struct FaceOfPast
{
    virtual void Smile() {printf(":) ");}
};
struct FaceOfFuture
{
    virtual void Smile() {printf(":) ");}
};
struct Janus : public FaceOfPast, public FaceOfFuture
{
};
int main()
{
   Janus* j = new Janus();
   j->Smile();
}

因为模棱两可。

根据C++标准(10.3.2):

如果在类 Base 中声明了虚拟成员函数 vf,并且在直接或间接派生自 Base 的类派生中声明了成员函数 vf,则声明了与 Base::vf

具有相同名称、参数类型列表、cv-限定符和 ref-qualifier(或不存在相同)的成员函数 vf,则 Derived::vf [...] 将覆盖 Basevf

似乎对多重继承没有任何特殊处理,因此它很可能也适用于这里:void Janus::Smile()覆盖这两个方法没有任何歧义,只是因为它与两个基类方法具有完全相同的名称和签名。

Janus* j = new Janus();
FaceOfFuture* future = j;
FaceOfPast* past = j;

这部分代码将强制转换为基类。因此,当您执行以下操作时

future->Smile();
past->Smile();

这实际上是指向FaceofPast和FaceOfFuture的指针。