4
1 #include <iostream>
2 using namespace std;
3 template<typename T>
4 class Top {
5 public:
6     class Sub {
7         protected:
8             T age;
9     };
10     class Derived : public Sub {
11         public:
12             void printAge() {
13                 cout << age << endl;
14             }
15     };  
16 };
17 int main()
18 {
19     return 0;
20 }

コードに準拠すると、次のエラーが発生します。

test.cpp: In member function ‘void Top<T>::Derived::printAge()’:
test.cpp:13:25: error: ‘age’ was not declared in this scope
             cout << age << endl;

でもテンプレじゃなくても大丈夫。回答をいただければ幸いです。

4

3 に答える 3

1

Derivedのageは、テンプレート内の名前です。標準で定義されている名前には 2 種類あります。

  • Dependent : テンプレート パラメーターに依存するが、テンプレート内で宣言されていない名前。
  • 非依存 : テンプレート パラメーターに依存しない名前、およびテンプレート自体の名前とその中で宣言された名前。

cout << age << endlの age は、テンプレートの定義の時点で解決される非依存の名前です。その時点では、Top::sub は後で特殊化される可能性があるため、コンパイラはまだ年齢を認識していません。したがって、基本クラスでは名前を検索しませんが、それを囲むスコープでのみ検索します。外側のスコープに age がないため、コンパイラは文句を言います。

this-> または Top:: を age に追加すると、依存するようになるため、ルックアップ ルールが変更されます。現在、年齢はテンプレートのインスタンス化の時点で解決されます。コンパイラは基本クラスを完全に理解し、名前を正しく解決できます。

于 2013-10-31T12:41:24.020 に答える
0
class Top<T>::Derived : public Top<T>::Sub

Deriveds 継承を考える別の方法です。このように考えると、 の変数Subは型に依存しているように見えますT。パラメーターの型に依存する変数を使用する場合、template多くの場合、明示的 ( Sub::age) にするか、メンバーであることを明確にする( ) 必要がありますthis->age

この場合、 base が に依存しているように見えますが、 base にTあるものを証明できます。ただし、これは、標準の細かい表現と、そのコーナーケースのコンパイラの実装 (成功するかどうか) に依存することになります。

したがって、問題を解決するにはthis->age、その状況で使用してください。

于 2013-10-31T12:40:01.610 に答える
0

ageテンプレート型パラメーターに依存するため、その評価はテンプレートのインスタンス化フェーズに対して行われます。このスレッドでわかるように、継承とテンプレートはうまく機能しません。派生クラスでのメンバーの使用は、最初の (宣言) フェーズでチェックされ、(上で述べたように) メンバーは 2 番目のフェーズで宣言 (「解析」) されます。そのため、メンバーが宣言されていないというコンパイラーの事柄。

これを解決する1つの方法は、ポインターを介してメンバーにアクセスしthis、コンパイラーに基本クラスをチェックさせることです。

于 2013-10-31T12:40:40.800 に答える