Frage

Diese Frage ist eine Förderung der in dieses Thema .

Die folgenden Klassendefinitionen verwenden:

template <class T>
class Foo {

public:
    Foo (const foo_arg_t foo_arg) : _foo_arg(foo_arg)
    {
        /* do something for foo */
    }
    T Foo_T;        // either a TypeA or a TypeB - TBD
    foo_arg_t _foo_arg;
};

template <class T>
class Bar : public Foo<T> {
public:
    Bar (const foo_arg_t bar_arg, const a_arg_t a_arg)
    : Foo<T>(bar_arg)   // base-class initializer
    {

        Foo<T>::Foo_T = T(a_arg);
    }

    Bar (const foo_arg_t bar_arg, const b_arg_t b_arg)
    : Foo<T>(bar_arg)
    {
        Foo<T>::Foo_T = T(b_arg);
    }

    void BarFunc ();

};

template <class T>
void Bar<T>::BarFunc () {
    std::cout << _foo_arg << std::endl;   // This doesn't work - compiler error is: error: ‘_foo_arg’ was not declared in this scope
    std::cout << Bar<T>::_foo_arg << std::endl;   // This works!
}

Wenn die Mitglieder der Basisklasse der Vorlage-Klasse zugreifen, wie es scheint, ich muss immer explizit die Mitglieder qualifizieren unter Verwendung der Schablone Stil Syntax von Bar<T>::_foo_arg. Gibt es eine Möglichkeit, dies zu vermeiden? Kann eine ‚Verwendung‘ Statement / Richtlinie ins Spiel kommt, in einer Methode Template-Klasse, um den Code zu vereinfachen?

Bearbeiten:

Der Umfang Problem wird durch die Qualifikation der Variable mit this-> Syntax aufgelöst.

War es hilfreich?

Lösung

Sie können this-> klar zu machen, verwenden Sie, dass Sie ein Mitglied der Klasse beziehen:

void Bar<T>::BarFunc () {
    std::cout << this->_foo_arg << std::endl;
}

Alternativ können Sie auch "using" in dem Verfahren verwendet werden:

void Bar<T>::BarFunc () {
    using Bar<T>::_foo_arg;             // Might not work in g++, IIRC
    std::cout << _foo_arg << std::endl;
}

Dies macht es für den Compiler klar, dass die Mitgliedsnamen so an den Template-Parametern abhängt, dass es für die Definition dieses Namens in den richtigen Stellen sucht. Weitere Informationen finden Sie auch diesen Eintrag in der C ++ FAQ Lite .

Andere Tipps

Hier ist die Basisklasse ist keine nondependent Basisklasse (die man mit einer kompletten Art bedeutet, die ohne Kenntnis der Vorlage Argumente bestimmt werden kann), und _foo_arg ist ein nondependent Name. Standard C ++ sagt, dass nondependent Namen nicht in den abhängigen Basisklassen nachgeschlagen.

Um den Code zu korrigieren, genügt es, den Namen _foo_arg abhängig zu machen, weil abhängig Name zum Zeitpunkt der Instanziierung nur nachgeschlagen werden kann, und zu diesem Zeitpunkt der genaue Basis Spezialisierung, die bekannt sein wird erforscht müssen. Zum Beispiel:

// solution#1
std::cout << this->_foo_arg << std::endl;

Eine Alternative besteht in einer Abhängigkeit Einführung eines qualifizierten Namen:

// solution#2
std::cout << Foo<T>::_foo_arg << std::endl;

Es muss bei dieser Lösung genommen werden, denn wenn der unqualifizierte nondependent Name, verwendet wird, einen virtuellen Funktionsaufruf zu bilden dann die Qualifikation den virtuellen Call-Mechanismus und die Bedeutung der Programmänderungen hemmt.

Und Sie können einen Namen aus einer abhängigen Basisklasse in der abgeleiteten Klasse bringen einmal durch using:

// solution#3
template <class T>
class Bar : public Foo<T> {
public:
    ...
    void BarFunc ();
private:
    using Foo<T>::_foo_arg;
};

template <class T>
void Bar<T>::BarFunc () {
    std::cout << _foo_arg << std::endl;   // works
}

Erscheint in Visual C ++ funktionieren 2008. Ich einige Dummy-Definitionen für die Typen hinzugefügt haben Sie erwähnt, aber gab keine Quelle für. Der Rest ist genau so, wie Sie es nennen. Dann wird eine Hauptfunktion BarFunc zu zwingen, instanziiert und aufgerufen werden.

#include <iostream>

class streamable {};
std::ostream &operator<<(std::ostream &os, streamable &s) { return os; }

class foo_arg_t : public streamable {};
class a_arg_t : public streamable {};
class b_arg_t : public streamable  {};

template <class T>
class Foo {

public:
    Foo (const foo_arg_t foo_arg) : _foo_arg(foo_arg)
    {
        /* do something for foo */
    }
    T Foo_T;        // either a TypeA or a TypeB - TBD
    foo_arg_t _foo_arg;
};

template <class T>
class Bar : public Foo<T> {
public:
    Bar (const foo_arg_t bar_arg, const a_arg_t a_arg)
    : Foo<T>(bar_arg)   // base-class initializer
    {

        Foo<T>::Foo_T = T(a_arg);
    }

    Bar (const foo_arg_t bar_arg, const b_arg_t b_arg)
    : Foo<T>(bar_arg)
    {
        Foo<T>::Foo_T = T(b_arg);
    }

    void BarFunc ();

};

template <class T>
void Bar<T>::BarFunc () {
    std::cout << _foo_arg << std::endl; 
    std::cout << Bar<T>::_foo_arg << std::endl;   
}

int main()
{
    Bar<a_arg_t> *b = new Bar<a_arg_t>(foo_arg_t(), a_arg_t());
    b->BarFunc();
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top