我有一个纯虚拟接口类和一个看起来像这样的派生类
class IInterface
{
public:
virtual void func() = 0;
};
class MyClass : public IInterface
{
public:
void func(int i) { func(); }
};
编译器抱怨func()
中对func(int i)
的调用不带0个参数。指定调用纯虚拟成员的正确方法是什么?
我提出的2个解决方案是
void func(int i) { static_cast<IInterface*>(this)->func(); }
和
void func(int i) { IInterface::func(); }
这些都可行吗?有没有更好的办法?两者看起来都很笨拙。
答案 0 :(得分:6)
使用 using-declaration 将基类声明带入派生类范围:
class MyClass : public IInterface
{
public:
using IInterface::func;
void func(int i) { func(); }
};
或者,将this
转换为指向base的指针也可以(即您的第一个选项):
void func(int i) { static_cast<IInterface*>(this)->func(); }
IInterface::func();
将无效,因为显式限定禁用了虚拟调度。
答案 1 :(得分:2)
如果您想避免从基类隐藏名称,可以使用using
语句:
class MyClass : public IInterface
{
public:
using IInterface::func; // prevents `func()` from being hidden by `func(int)`
void func(int i) { func(); }
};
这在第33项中描述:&#34;避免隐藏继承的名称&#34;斯科特迈耶斯&#39; &#34;有效的C ++,第三版&#34;。
答案 2 :(得分:1)
代码void func(int i) { func(); }
不起作用,因为当您在func
范围内声明MyClass
时,该名称会隐藏基类中名为func
的任何其他名称。
如果您希望IInterface
的{{1}}通常在范围func()
中使用,则最简单的解决方案是:
MyClass
可以进入MyClass的类定义(并且会尊重你把它放在的访问说明符);或者你只能把它放在using IInterface::func;
里面。完成此操作后,从func(int i)
范围内调用func
会在MyClass
和func()
之间执行重叠解析。
func(int)
也可以使用:它会为您当前使用的对象调用static_cast<IInterface*>(this)->func();
的最终覆盖。
版本func()
不进行虚拟调度;它实际上调用了特定的函数IInterface::func()
。如果您没有定义这样的函数,那么您将导致未定义的行为;这可能会显示为链接器错误,或者是关于尝试调用纯虚函数的运行时错误。
NB。如果你不知道,纯虚函数也可能有一个正文定义,但这很少在析构函数之外完成。