2014-01-16 61 views
14

請考慮下面的代碼:C++:正確重寫虛函數模板類

template<typename T> 
struct MyTempl 
{ 
    virtual void doStuff(const T &value) = 0; 
}; 

struct MyImpl : MyTempl<int> 
{ 
    void doStuff(const int &value) {} 
}; 

struct MyPtrImpl : MyTempl<int*> 
{ 
    void doStuff(const int* &value) {} 
}; 

MyImpl imp1; 
MyPtrImpl imp2; 

這不會正確編譯:編譯器告訴我,doStuff()MyPtrImpl是純虛擬的,即。我未能正確覆蓋它。但是,如果我輸入到int_ptr之類的東西,並將其作爲MyPtrImpl的模板參數,則一切正常。

爲什麼編譯器無法在沒有typedef的情況下扣除我的意圖?

回答

17

您沒有指定虛擬函數的正確參數類型,因此您不覆蓋它。由於虛函數是純粹的,因此這會產生一個抽象類。

當指定像

const引用類型的參數它實際上是寫一個替代

void doStuff(int const & value) {} 

應該被認爲是「正常」的方式來聲明恆定的基準。當從右向左讀時,這意味着「對常數int的引用」。應用相同的圖案,將指針類型int*導致

void doStuff(int* const & value) {} 

which compiles fine。但是不能按照上面的順序編寫,因爲這意味着不同的東西:從右到左讀const int* &,並且您得到「對指向常量int的指針的引用」。

至於你提到它,這與從上方的順序工作的替代,可以如果使用的typedef別名指針類型int*寫成:

typedef int *T; 
void doStuff(const T & value) {} 

which also compiles fine,由於T現在看作單個字面類型不引入上面的含糊之處。換句話說,如何閱讀const T &的唯一選擇是「對const T的引用,該引用本身是指向int的指針」。直觀地理解它有點困難,但不可能的是將其理解爲「對指向常數int的指針的引用」,因爲在描述中這不會有單個T

如果您使用C++ 11編譯器來檢測這樣的問題,我推薦使用關鍵字override(有些情況下,此問題不會導致編譯錯誤,但會導致意外的行爲;對於例如,如果虛函數是純):

void doStuff(int* const & value) override {} 
//        ^^^^^^^^ 
+4

...這就是爲什麼* *權的const''位置始終是正確的。 +1 –

+0

@DavidRodríguez-dribeas然而,大多數人使用*左*版。如果我沒有記錯的話,包括標準規範中的大部分代碼...... – leemes

+0

'從右向左讀'const int *&',並且得到「指向常量int的指針」。 - 這就是我需要知道的,謝謝! – Ancurio