基类:
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()
。所有这些都是因为函数签名在Base
和Derived
类中匹配。如果签名不匹配,那么这只是一个重新定义,在这种情况下,它会在Derived
类中隐藏Base::f()
。