当存在另一个具有另一个签名的成员时,调用纯虚成员的正确方法是什么?

What is the correct way to call the pure virtual member when another member exists with another signature?

本文关键字:成员 另一个 是什么 方法 调用 存在      更新时间:2023-10-16

我有一个纯虚接口类和一个派生类,如下所示

class IInterface
{
public:
    virtual void func() = 0;
};
class MyClass : public IInterface
{
public:
    void func(int i) { func(); }
};

编译器报错func(int i)中对func()的调用没有接受0个参数。什么是指定调用纯虚成员的正确方法?

我想到的两个解决方案是

void func(int i) { static_cast<IInterface*>(this)->func(); }

void func(int i) { IInterface::func(); }

这两个都可行吗?有没有更好的办法?

使用using-declaration:

将基类声明引入派生类作用域
class MyClass : public IInterface
{
public:
    using IInterface::func;
    void func(int i) { func(); }
};

或者,将this转换为指向基的指针也可以工作(即,您的第一个选项):

void func(int i) { static_cast<IInterface*>(this)->func(); }

IInterface::func();不能工作,因为显式限定禁用虚拟调度。

如果您想避免在基类中隐藏名称,您可以使用using语句:

class MyClass : public IInterface
{
public:
    using IInterface::func;      // prevents `func()` from being hidden by `func(int)`
    void func(int i) { func(); }
};

这在Scott Meyers的"Effective c++, Third Edition"的第33条:"避免隐藏继承的名称"中有描述。

代码void func(int i) { func(); }不起作用,因为当您在MyClass的范围内声明func时,该名称隐藏了基类中称为func的任何其他名称。

如果您希望IInterfacefunc()MyClass作用域中普遍可用,最简单的解决方案是:

using IInterface::func;

可以放在MyClass的类定义中(并且会尊重你把它放在下面的访问说明符);或者你只能把它放在func(int i)里面。在此之后,从MyClass的作用域调用func将在func()func(int)之间进行过载解析。


static_cast<IInterface*>(this)->func();也可以工作:它将为当前正在处理的对象调用func()的最终重写。

IInterface::func()版本不做虚调度;它实际上调用了特定的函数IInterface::func。如果你没有定义这样一个函数,那么你将导致未定义的行为;这可能会显示为链接器错误,或者试图调用纯虚函数的运行时错误。

NB。如果你不知道,纯虚函数也可以定义一个函数体,但这很少在析构函数之外完成。

相关文章: