[gelöst] Template Klasse ableiten
-
Muss ich da etwas beachten?
Ich hab jetzt eine Subclass erstellt und die Variablen in der Oberklasse protected gesetzt, seit ich meine Klasse als Template laufen lasse, kann ich aber in der abgeleiteten Klasse nicht mehr auf die protected Daten zugreifen.abegleitet hab ich so
template <typename T> class ExtListe:public Liste<T>{};
-
codyjack schrieb:
Muss ich da etwas beachten?
Nö.
codyjack schrieb:
Ich hab jetzt eine Subclass erstellt und die Variablen in der Oberklasse protected gesetzt, seit ich meine Klasse als Template laufen lasse, kann ich aber in der abgeleiteten Klasse nicht mehr auf die protected Daten zugreifen.
Müsste noch gehen. Aber Du verschweigst bestimmt das ein oder andere Detail.
codyjack schrieb:
abegleitet hab ich so
template <typename T> class ExtListe:public Liste<T>{};Geht das auch noch etwas ausführlicher?
Gruß,
SP
-
klar gehts auch ausführlicher

template <typename T> class Liste { protected: int _size; int _last; int _pos; T *values; bool isFull(); bool isEmpty(); void increase(); public: Liste(); ~Liste(); void insert(T key); T get(T key); void erase(T key); T top(); void pop(); }; //******************************************************************** template <typename T> class ExtListe:public Liste<T>{ public: bool contains(T key); void erase(T val); string toScreen(); };
-
codyjack schrieb:
Muss ich da etwas beachten?
Ja. Der Scope einer Basisklasse, welche von einem Templateparameter abhängig ist, wird nicht automatisch in die Suche nach Typen, Variablen, Funktionen usw. aufgenommen.
Also kurz:
template<typename T> struct Base { void foo() { } }; template<typename T> struct Derived : public Base<T> // <- Basisklasse ist vom Templateparameter abhängig. { void bar() { foo(); // Per Standard ein Fehler, wird nicht gefunden. this->foo(); // geht. Base<T>::foo(); // geht. } };Grüssli
-
ah Danke, damit gehts, aber gibts keine Möglichkeit ohne Scope Operator zu arbeiten?
-
codyjack schrieb:
ah Danke, damit gehts, aber gibts keine Möglichkeit ohne Scope Operator zu arbeiten?
Wie schon gezeigt über
this. Ansonsten, wenn du gewisse Funktionen Objekte oder ähnliches mehrmals brauchst, dann kannst du diese Namen manuell raufziehen:template<typename T> struct Base { void foo() { } }; template<typename T> struct Derived : public Base<T> // <- Basisklasse ist vom Templateparameter abhängig. { using Base<T>::foo; // raufziehen. void bar() { foo(); // funktioniert } };Das geht aber nicht immer und man sollte bei solchen Sache vorsichtig sein, da es plötzlich zu ungewollten Überladungen statt Überdeckungen kommen könnte.
Auch ist es nicht wirklich sehr schön, wenn man viele solcherusingAnweisungen hat
Wenn du übrigens eine Funktion über
Base<T>::foo()aufrufst, sollte dir auch bewusst sein, dass die Funktion nicht virtuell aufgerufen wird, beithis->foo()allerdings schon.Grüssli
-
Wo ist denn die Problemstelle und welche Fehlermeldung bekommst Du?!
Wenn ich raten müsste, würde ich auf das "Zwei-Phasen-Lookup" tippen:
template<typename T> struct foo { int x; }; template<typename T> struct bar : foo<T> { void blupp() { x = 23; // <-- Fehler, Compiler kennt x nicht } };Der Compiler verarbeitet so ein Template in zwei Phasen. Die erste Phase ist die Überprüfung bevor Du dieses Template spezialisiert ("instantiierst"). Die zweite Phase ist dann die Spezialisierung selbst, in der der Compiler für T einen bestimmten Typ einsetzt, und die Klasse erzeugt. In der ersten Phase versucht der Compiler schon möglichst viele Namen aufzulösen, damit Programmierfehler früh erkannt werden können.
In Deinem Fall ist die Basisklasse vom Template-Parameter abhängig. Das macht den Typ der Basisklasse zu einem "abhängigen Typen". In der ersten Phase weiß der Compiler also nicht, was List<T> eigentlich genau ist, da T noch nicht weiter spezifiziert wurde. Aus diesem Grund kann der Compiler 'x' auch nicht zuordnen. Er geht davon aus, dass x nicht Teil der Basisklasse ist und sucht in anderen Namensräumen nach x.
Um das Problem zu beheben, musst Du dem Compiler signalisieren, dass es sich bei x um ein Element der Klasse handelt:
template<typename T> struct bar : foo<T> { void blupp() { this->x = 23; // OK } };Warum funktioniert das so? Naja, der Compiler sieht das "this->" und weiß, jetzt muss ein Mitglied der Klasse kommen. Und da die Klasse von einem abhängigen Typen ableitet, wird die Namensauflösung von x in die "zweite Phase" verschoben.
Mehr dazu gibt es in schlauen C++ Büchern.
Gruß,
SP
-
Mist! ... war ich wohl zu langsam diesmal.

Bei
usingundbasisklasse::sollte man in Kombination mit virtuellen Funktionen aber aufpassen.Gruß,
SP
-
OK Vielen Dank soweit
