为什么在虚拟函数声明中使用不同的返回类型会引发错误,而不是导致重新定义



基类:

class Base
{
public:
virtual int f() const
{
return 1;
}
};

派生类:

class Derived: public Base
{
public:
void f() const {}
};

上面的代码抛出一个";返回类型不相同/协变错误";。

我读过一些关于它的讨论。这一次是类似的,但他们只是说,如果返回类型不相同/协变,它会破坏代码。用不同的返回类型覆盖成员函数

为什么我期待的行为没有发生?

预期行为:Derived中的VPTR指向Base::f(((我已经读过,如果没有为虚拟函数提供重写,那么Derived对象将只使用继承的类版本(。它还隐藏了名称f((,所以现在调用如下:

Derived x;
x.f();

应该调用Derived::f((和类似这样的调用:

x.Base::f();

应该调用Base::f((函数。这似乎并没有破坏代码。即使在upcasted中,它也不应该破坏代码,因为两个类的VPTR都指向相同的Base::f((

我能想到的唯一原因是,这样的声明(相同的签名和协变/相同的返回类型(是为重写虚拟方法而保留的,我们不能用它来引起我期望的行为。

当编译器遇到匹配的签名(参数、常量(时,它会自动使void f() const声明成为虚拟的。因此Derived的定义被解释为:

class Derived: public Base
{
public:
virtual void f() const {} // virtual keyword is added
};

这显然看起来像是试图覆盖Base::f()。所有这些都是因为函数签名在BaseDerived类中匹配。如果签名不匹配,那么这只是一个重新定义,在这种情况下,它会在Derived类中隐藏Base::f()

最新更新