2014-01-16 11 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; 

これは正しくコンパイルされません。コンパイラは、MyPtrImpldoStuff()はすなわち、仮想純粋であることを私に伝えます。私はそれを正しく無視できませんでした。しかし、int*int_ptrのようにタイプして、それをMyPtrImplのテンプレート引数として使用すると、すべてがうまくいきます。

コンパイラがtypedefなしで自分のインテントを差し引くことができないのはなぜですか?

答えて

17

仮想関数の正しいパラメータ型を指定していないため、オーバーライドしていません。仮想関数は純粋なので抽象クラスになります。

それは実際に一定の基準を宣言するために、「通常」の方法と考えるべきである

void doStuff(int const & value) {} 

を書くための代替です

などのconst参照型のパラメータを指定します。右から左へ読むと、これは「定数への参照」を意味します。int

void doStuff(int* const & value) {} 

which compiles fineにおけるポインタ型int*結果と同一のパターンを適用します。しかし、それは上記のような順序で書くことはできません。これは何か異なることを意味するでしょう:右から左へconst int* &を読み、 "intの定数への参照への参照"を取得します。

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

which also compiles fineTが1つのリテラルとして見られているので、:あなたはそれを言及したように、あなたがポインタ型int*を別名するのtypedefを使用する場合

、上から順に作品の代替を書き込むことができます上から曖昧さを導入しないようにしてください。つまり、const T &を読み取る唯一のオプションは、「Tの参照への参照です。それ自体はintへのポインタです」ということです。直感的に理解するのは少し難しいですが、これは "int"へのポインタへの参照として理解することです。これはという単一のTの説明には含まれないためです。

このような問題を検出するためにC++ 11コンパイラを使用している場合は、キーワードoverrideを使用することをお勧めします。この問題がコンパイルエラーにならず予期しない動作になるシナリオがあります。たとえば仮想関数)がない純粋であった場合:

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

... const' 'の*右*場所は常に正しい理由です。 +1 –

+0

@DavidRodríguez-dribeasしかし、ほとんどの人は* left *バージョンを使用しています。もし私が正しく覚えていれば、標準仕様に大部分のコードを含めると... – leemes

+0

'const int *& 'を右から左に読んで、あなたは"定数intへのポインタへの参照 "を取得します。 - それは私が知る必要があったすべてです、ありがとう! – Ancurio

関連する問題