
Schwindler
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!
}
Beim Zugriff auf die Mitglieder der Basisklasse der Vorlagenklasse scheint es, als müsste ich die Mitglieder immer explizit qualifizieren, indem ich die Syntax im Vorlagenstil von verwende Bar<T>::_foo_arg
. Gibt es eine Möglichkeit, dies zu vermeiden? Kann eine ‘using’-Anweisung/Direktive in einer Template-Klassenmethode ins Spiel kommen, um den Code zu vereinfachen?
Bearbeiten:
Das Bereichsproblem wird gelöst, indem die Variable mit this-> Syntax qualifiziert wird.

etw
Sie können verwenden this->
um deutlich zu machen, dass Sie sich auf ein Mitglied der Klasse beziehen:
void Bar<T>::BarFunc () {
std::cout << this->_foo_arg << std::endl;
}
Alternativ können Sie auch “using
” in der Methode:
void Bar<T>::BarFunc () {
using Bar<T>::_foo_arg; // Might not work in g++, IIRC
std::cout << _foo_arg << std::endl;
}
Dadurch wird dem Compiler klar, dass der Elementname von den Vorlagenparametern abhängt, sodass er an den richtigen Stellen nach der Definition dieses Namens sucht. Weitere Informationen finden Sie auch unter diesen Eintrag in den C++ Faq Lite.

songyuanyao
Hier ist die Basisklasse keine nicht abhängige Basisklasse (d. h. eine mit einem vollständigen Typ, der bestimmt werden kann, ohne die Template-Argumente zu kennen), und _foo_arg
ist ein unabhängiger Name. Standard-C++ sagt, dass nicht abhängige Namen nicht in abhängigen Basisklassen nachgeschlagen werden.
Um den Code zu korrigieren, genügt es, den Namen zu machen _foo_arg
abhängig, 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 mit einem qualifizierten Namen einzuführen:
// solution#2
std::cout << Foo<T>::_foo_arg << std::endl;
Bei dieser Lösung ist Vorsicht geboten, denn wenn der unqualifizierte unabhängige Name verwendet wird, um einen virtuellen Funktionsaufruf zu bilden, verhindert die Qualifizierung den virtuellen Aufrufmechanismus und die Bedeutung des Programms ändert sich.
Und Sie können einen Namen von einer abhängigen Basisklasse in die abgeleitete Klasse einmal durchbringen 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
}
Scheint in Visual C++ 2008 gut zu funktionieren. Ich habe einige Dummy-Definitionen für die von Ihnen erwähnten Typen hinzugefügt, aber keine Quelle dafür angegeben. Der Rest ist genau so, wie du es beschreibst. Dann eine Hauptfunktion erzwingen BarFunc
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();
}
9985200cookie-checkAbgeleiteter Vorlagenklassenzugriff auf Elementdaten der Basisklasseyes