2012-04-16 5 views
5

A. hWarum kann ich keine Variable der übergeordneten Klasse verwenden, die eine Vorlagenklasse ist?

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

b.h

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; 
} 

warum passiert den Fehler, wenn ich nicht this-> verwenden?

Kann ich this-> mit einer Methode weglassen?

(Ich reparierte einige Fehler)

+0

Joachim Pileborg gab Ihnen die Antwort. Darüber hinaus hat der bereitgestellte Code andere Probleme, die die Kompilierung verhindern. – Anonymous

+0

Ist das der eigentliche Code?Nach den Klassendefinitionen gibt es keine abschließenden Semikolons und der Bereichsoperator für 'int B : f() 'ist falsch plus kein Semikolon in der Fehlerzeile. – hmjd

+0

oh, es ist nur ein Tippfehler. Ich habe es repariert. –

Antwort

11

Es gibt zwei Phasen in der Template-Instantiierung ("Two Phase Namenssuche").

In der ersten Phase werden alle nicht abhängigen Namen aufgelöst (nachgeschlagen). In der zweiten Phase werden abhängige Namen aufgelöst.

Ein abhängiger Name ist ein Name, der auf einem Template-Parameter abhängig ist, z.B .:

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. 
} 

Jetzt schreiben Sie:

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

Das ist genau das, was ich beschrieben. In Ordnung, t wird in Phase 2, nachgeschlagen, da this von einem Template-Parameter abhängt.

Der fehlerbehaftete Begriff wird in Phase 1 nachgeschlagen, da nichts in diesem Namen von einem Vorlagenparameter abhängt. In Phase 1 ist jedoch a nicht sichtbar, da der Compiler die Basisklassenvorlagen in Phase 1 nicht untersuchen kann, da Vorlagen spezialisiert werden können und zum Zeitpunkt der Instanziierung entfernt von der primären Vorlagedeklaration eine andere Spezialisierung sein kann das hat keine a, könnte sichtbar sein.

Beispiel:

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 
    } 

BTW, habe ich einmal geschrieben this-> is not only a matter of style in meinem sehr niedrigen Frequenz Blog.

+0

Ein abhängiger Name ist ein Name, der nicht von einem Template-Parameter abhängt -> Ein abhängiger Name ist ein Name, der von einem Template-Parameter abhängt:) – czxyl

+0

@czxyl: Fast ein halbes Jahrzehnt, um diesen Fehler aufzudecken: D Danke für den Hinweis:) –

1

B ist eine Vorlage, und daher sind ihre Namen nicht abhängig und müssen daher nach der Definition der Vorlage gesucht werden, nicht wenn sie instanziiert wird. Zum Zeitpunkt der Definition der Vorlage sind die abhängigen Namen jedoch nicht bekannt (möglicherweise gibt es Spezialisierungen der Basisklassenvorlage A, die bisher nicht angezeigt wurden). Der Compiler kann den nicht qualifizierten Namen nicht in die Basisklasse auflösen. Sie können entweder bringen die Namen in den aktuellen Bereich durch this-> Qualifikation, indem sie sie mit A<T>:: oder mit einer using Erklärung vorangestellt:

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

Beachten Sie auch, dass Sie, wo fehlende Semikolons nach den Klassendeklarationen und die Linie markiert mit der // Error Kommentar.

+0

"Die abhängigen Namen sind nicht bekannt" -> Dies macht im C++ - Sprachgebrauch keinen Sinn. Ein Name könnte abhängig sein oder nicht, z. mit Typname T ist 'A :: x' ein abhängiger Name,' x' nicht. Es mag für Sie als Programmierer Sinn machen, dass "x" ein abhängiger Name ist, aber technisch gesehen ist "x" kein abhängiger Name. –

+0

-1: "seine Namen sind nicht abhängig und müssen daher nachgeschlagen werden" -> Das ist falsch. Es kann Mitgliedsnamen geben, die abhängig sind. Beispiel: http://ideone.com/zIa7k –

+0

-1: 'this->' hat nichts zu tun mit Scoping. –

Verwandte Themen