6

ああ

template <typename T>
class A
{
    public:
    int a;
}

bh

template <typename T>
class B : public A<T>
{
   public:
   int f();
}

template <typename T>
int B<T>::f()
{
    int t;
    t = this->a; //Okay
    t = a //Error
    return 0;
}

を使用しないとエラーが発生するのはなぜthis->ですか?

this->何らかの方法で省略できますか?

(一部ミスを修正しました)

4

2 に答える 2

15

テンプレートのインスタンス化には 2 つのフェーズがあります (「2 フェーズの名前検索」)。

最初のフェーズでは、すべての非依存名が解決 (ルックアップ) されます。2 番目のフェーズでは、従属名が解決されます。

従属名は、テンプレート パラメータに依存する名前です。たとえば、次のようになります。

template <typename T>
void foo() {
    x = 0;    // <- Non-dependent, nothing in that refers to "T".
              //    Thus looked up in phase 1, therefore, an 'x' must be
              //    visible.

    T::x = 0; // <- Dependent, because it depends on "T".
              //    Looked up in phase 2, which is when it must be visible.
}

ここで、次のように記述します。

t = this->a; //Okay
t = a //Error

これはまさに私が説明したことです。テンプレートパラメータに依存するtため、フェーズ 2 でルックアップされます。this

エラーのある用語はフェーズ 1 で検索されます。これは、その名前にはテンプレート パラメーターに依存するものがないためです。ただし、フェーズ 1 では、noaが表示されます。これは、コンパイラがフェーズ 1 で基本クラス テンプレートをイントロスペクトできないためです。テンプレートは特殊化でき、インスタンス化の時点で、プライマリ テンプレート宣言から離れているa可能性があるためです。目に見える。

例:

    template <typename T>
    struct Base {
    };


    template <typename T>
    struct Derived : Base<T> {
        void foo() {
            this->a = 0; // As is valid. `this->a` is looked up in phase 2.
        }
    };


    template <> struct Base<int> {
        int a;            
    };


    int main () 
    {
            // The following declarations trigger phase 2 lookup.

            Derived<int>   di;  // valid, because a later specialized
                                // Base<int> is used and all symbols
                                // are resolved.

            Derived<float> df;  // not valid
    }

ところで、私はかつてこれを書いたことがあります- >私の非常に頻度の低いブログのスタイルの問題だけではありません.

于 2012-04-16T09:19:10.953 に答える
1

Bはテンプレートであるため、その名前は非依存であるため、テンプレートがインスタンス化されたときではなく、テンプレートが定義されたときに検索する必要があります。ただし、テンプレートの定義時には、従属名が不明なため (Aこれまでに見られなかった基底クラス テンプレートの特殊化が存在する可能性があります)、コンパイラは非修飾名を基底クラスに解決できません。名前を前に付けるか、宣言this->を付けることで、修飾によって現在のスコープに名前を入れることができます。A<T>::using

template <typename T>
class B : public A<T>
{
   public:
   using A<T>::a;
   int f();
};

// Errorまた、クラス宣言とコメントでマークされた行の後にセミコロンがないことに注意してください。

于 2012-04-16T09:31:16.453 に答える