在派生類中,函數簽名是這樣的:
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