Diese Frage ist eine Weiterentwicklung der in diesem Thread gestellten Frage .
Verwenden der folgenden Klassendefinitionen:
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 ich auf die Mitglieder der Basisklasse der Vorlagenklasse zugreife, muss ich die Mitglieder anscheinend immer explizit mit der Syntax des Vorlagenstils von qualifizieren Bar<T>::_foo_arg
. Gibt es eine Möglichkeit, dies zu vermeiden? Kann eine 'using'-Anweisung / Direktive in einer Vorlagenklassenmethode ins Spiel kommen, um den Code zu vereinfachen?
Bearbeiten:
Das Scope-Problem wird behoben, indem die Variable mit dieser-> Syntax qualifiziert wird.
quelle
Hier ist die Basisklasse keine nicht abhängige Basisklasse (dh eine mit einem vollständigen Typ, der ohne Kenntnis der Vorlagenargumente bestimmt werden kann) und
_foo_arg
ist ein nicht abhängiger Name. Standard C ++ besagt, dass nicht abhängige Namen in abhängigen Basisklassen nicht nachgeschlagen werden.Um den Code zu korrigieren, reicht es aus, den Namen
_foo_arg
abhängig zu machen, da abhängige Namen nur zum Zeitpunkt der Instanziierung nachgeschlagen werden können und zu diesem Zeitpunkt die genaue Basisspezialisierung bekannt ist, die untersucht werden muss. Zum Beispiel:// solution#1 std::cout << this->_foo_arg << std::endl;
Eine Alternative besteht darin, eine Abhängigkeit unter Verwendung eines qualifizierten Namens einzuführen:
// solution#2 std::cout << Foo<T>::_foo_arg << std::endl;
Bei dieser Lösung ist Vorsicht geboten, denn wenn der nicht qualifizierte, nicht abhängige Name zur Bildung eines virtuellen Funktionsaufrufs verwendet wird, verhindert die Qualifizierung den virtuellen Aufrufmechanismus und die Bedeutung des Programms ändert sich.
Und Sie können einen Namen aus einer abhängigen Basisklasse in die abgeleitete Klasse einmal einbringen, indem Sie
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 }
quelle
Scheint in Visual C ++ 2008 einwandfrei zu funktionieren. Ich habe einige Dummy-Definitionen für die von Ihnen genannten Typen hinzugefügt, aber keine Quelle angegeben. Der Rest ist genau so, wie Sie es ausdrücken. Dann eine Hauptfunktion zu erzwingen
BarFunc
, instanziiert und aufgerufen zu 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(); }
quelle