在派生类中,函数签名是这样的:
virtual void foo(); //Derived::foo
没有提及const
。它是一个非const成员函数,而Base::foo
是一个const成员函数。它们是两种不同的功能,因为const
是函数签名的一部分。
virtual void foo() const; //Base::foo
派生类不重写此函数,而是增加了另一个函数。
所以修复是这样的:
class Derived : public Base {
public:
virtual void foo() const {
cout << "Derived::foo()" << endl;
}
};
由于const
是函数签名的一部分。所以当你打算重写base的foo时你必须提及它。
@ davka真实问:
为什么const版本选择在非const?有没有任何规则,或只是碰巧是第一个选择?
它,因为静态型obj
为Base
,和函数的名称是基于静态类型对象的解决。 Base
甚至没有非常量版本。所以它没有被选中或拒绝的问题。它不存在于Base
开始。
void func(Base& obj) {
obj.foo(); //calls Base::foo
}
但是,如果更改上面的代码如下:
void func(Derived & obj) {
obj.foo(); //calls Derived:foo
}
现在非const版本将被选中,因为Base::foo
隐藏在Derived
类。
由于Derived::foo
隐藏Base::foo
,所以使用的Derived
一个实例,你不能调用后者。
现在,让我们取消隐藏Base::foo
并做一些更多的实验。
class Derived : public Base {
public:
using Base::foo; //<----------------this unhides Base::foo
virtual void foo() {
cout << "Derived::foo()" << endl;
}
};
现在派生,两者的功能(常量和非const版本)可供选择,取消隐藏。现在几个有趣的问题。
由于现在Derived同时具有两个函数,所以函数将在下面的每个函数中调用?
void f(Derived& obj) {
obj.foo(); //Which function? Base::foo or Derived::foo?
}
void g(const Derived & obj) {
obj.foo(); //Which function? Base::foo or Derived::foo?
}
第一个将调用Derived::foo
其是非const版本,和第二个将调用Base::foo
这是const版本。原因很简单,只有const对象,只有const函数可以被调用,但是对于非const对象,两者都可以被调用,但是如果可用则选择非const版本。
见在线演示:http://www.ideone.com/955aY
1)不是重写2)是 – AJG85 2011-06-10 15:42:06
如果签名不同,它不是重写! – 2011-06-11 01:18:45