2016-09-23 9 views
0

次のコードをコンパイルするときにこのエラーが発生しました。 いくつかの研究を行い、さまざまな状況で同様のエラーを読んだ後、私は必要な解決策を考え出しました。 しかし、私はエラーと修正のための激しい理由を完全に理解していませんでした。このコードをコンパイルするときテンプレート継承:テンプレートパラメータに依存する引数がありません

template <typename T> 
class TestA { 
    int a; 
    T temp; 

protected: 
    int b; 

public: 
    int c; 

    TestA(T te): a{10}, b{20}, c{30}, temp{te} {} 

    int geta(){ return a; } 
    int getb(){ return b; } 
    int getc(){ return c; } 
}; 

template <typename T> 
class TestB { 
    int atb; 
    T tempb; 

protected: 
    int btb; 

public: 
    int ctb; 

    TestB(T te) atb{10}, btb{20}, ctb{30}, tempb{te} {} 
}; 

template <typename T> 
class TestInh : public TestA<T>, public TestB<T> { 
    int aa; 
    T temptemp; 

protected: 
    int bb; 
    int b; 

public: 
    int cc; 

    TestInh(T te) : TestA<T>{te}, TestB<T>{te}, bb{10000}, b{-1000} {} 

    int get_total() { 
     // The error happens here! 
     return geta(); 
    } 
}; 

int main(int argc, char const *argv[]) { 
    char text = 'a'; 
    TestInh<char> test(text); 

    //std::cout << test.geta() << std::endl; 
    std::cout << test.get_total() << std::endl; 
    //std::cout << test.c << std::endl; 
    return 0; 
} 

、私はこのエラーを得た:

testtemplate.cc: In member function ‘int TestInh<T>::get_total()’: 
testtemplate.cc:54:32: error: there are no arguments to ‘geta’ that depend on a template parameter, so a declaration of ‘geta’ must be available [-fpermissive] 
int get_total() {return geta();} 
          ^
testtemplate.cc:54:32: note: (if you use ‘-fpermissive’, G++ will accept your code, but allowing the use of an undeclared name is deprecated) 

それはthis->geta()を呼び出すだけではなくgeta()によって解決されるが、これは、コンパイラによって解決することができない理由を私は完全には理解していません。

誰かが私の理由を説明できますか?

+0

それは@Gpg MSVCは、間違っているVS2015でコンパイル – GpG

+0

関数はメンバ関数として存在してコンパイラに言うのもう一つの方法は、usingステートメントを追加することです。その中に 'template'というキーワードがあるものは、それに頼らないでください。 –

答えて

4

テンプレートパラメータに依存するクラスを拡張する場合、thisの種類は従属名になります。

問題は、2つのフェーズの名前検索を実行しているときに、コンパイラはどこで関数getaを見つけることができないのかを知ることができないということです。彼はそれが親から来ているのか分からない。テンプレートの特殊化は事なので、TestA<int>TestA<double>は、異なる機能とメンバーを持つ2つの全く異なるクラスである可能性があります。

thisキーワードを追加すると、コンパイラはgetaがメンバ関数である必要があることを認識しています。

これがないと、メンバー関数またはメンバー以外の関数か、メンバー関数TestBのいずれかになります。

一部のテンプレート条件によっては、TestAgetaからTestBへの関数getaを呼び出すテンプレートコードを想像してください。ああ。コンパイラは、コードがすべてのテンプレートインスタンシエーションに対して一貫していることを確認します。

template <typename T> 
struct TestInh : TestA<T>, TestB<T> { 
    // some code... 

    using TestA<T>::geta; 

    int get_total() { 
     // works! With the above using statement, 
     // the compiler knows that 'geta()' is 
     // a member function of TestA<T>! 
     return geta(); 
    } 
}; 
+0

ありがとう!これは私が探していたものです。 – luisremis

関連する問題