Variablen einer Basisklasse ansprechen
-
Gibt es noch eine andere möglichkeit die Variablen einer abgeleiteten Klasse anzusprechen? Ich finde das using nicht so schön aussieht, besonders wenn die abgeleitete Klasse mehrere Variablen besitzt.
-
Du kannst die Member direkt über den
:: - Operatoransprechen. Um an das Beispiel anzuhängen:template<typename T> class derived : public base<T> { //using base<T>::data; public: void foo() { std::cout << base::data; } };
-
Hmm ok es scheint wohl keine optimale Lösung zu geben, die eine Änderung der Klasse verhindert.
template<class T> class IFoo { public: T _data; }; template<class T> class Foo:public IFoo<T> { using IFoo::_data; //Das wollte ich vermeiden. public: Foo() { IFoo::_data; //Das wollte ich auch vermeiden. _data; //Dieser Zugriff wär mir am liebsten gewesen. } };So wie es aussieht muss ich bei dem Compiler Code::Blocks 8.02 immer wenn ich Klassen, die Templates benutzen, ableite, alle Variablen direkt ansprechen. Schade das ich den Compiler nicht sagen kann das diese Variablen in der Klasse IFoo sind.
-
@Gast123,
1. Code::Blocks ist kein Kompiler, sondern eine IDE. Meistens wird dort der GCC als Kompiler verwendet, allerdings kann man mit Code::Blocks ohne grosse Probleme auch andere Kompiler verwenden. Das nur zur Klarstellung.
2. Das Problem hat nichts mit dem Kompiler zu tun, sondern ist so im C++ Standard definiert. Das Problem ist, dass deine Basisklasse abhängig von einem Template Parameter ist. Dabei ist es unmöglich vor der Instanzierung der Templateklasse zu wissen, was für eine Basisklasse hier tatsächlich verwendet wird. Stichwort: Spezialisierung. Daher muss man dem Kompiler explizit mitteilen, dass er am entsprechenden Ort dann suchen soll. Kurzes Beispiel zur Verdeutlichung:template<typename> struct Base { int a; }; template<> struct Base<int> { // keine Variable. }; int a; // globale Variable template<typename T> struct Derived : Base<T> // Was wird hier als Basisklasse genommen? Wir wissen es noch nicht! { void foo() { std::cout << a << std::endl; // Es wird das falsche a verwendet, da wir noch nicht wissen, // welche Basisklasse verwendet werden wird. Im externen Scope // kann man allerdings bereits suchen, da dieser bekannt ist. // Deshalb wir hier das globale a verwendet. std::cout << this->a << std::endl; // Wir sagen dem Kompiler, dass es ein a in der Klasse geben muss. // Wenn dies nicht der Fall ist, wird es bei der Instanzierung der // Templateklasse zu einem Fehler kommen. std::cout << Base<T>::a << std::endl; // Grundsätzlich das gleiche wie oben, nur dass wir hier explizit // sagen, wo gesucht werden soll. Das ist übrigens ein wichtiger // Unterschied, betrifft vor allem das Aufrufen von Funktionen. } };3. Dein Design ist sehr fragwürdig. Die Lesbarkeit wird meiner Meinung nach definitiv nicht erhöht. Schon nur, weil du die Variablen nicht
privatemachst. Du veränderst die Variablen direkt aus anderen Klassen heraus. Dadurch wird es völlig unmöglich irgendwelche Annahmen über die Variablen in der Basisklassen zu machen. Membervariablen sollten so gut wie immerprivatesein.Grüssli
-
Dravere schrieb:
@Gast123,
1. Code::Blocks ist kein Kompiler, sondern eine IDE. Meistens wird dort der GCC als Kompiler verwendet, allerdings kann man mit Code::Blocks ohne grosse Probleme auch andere Kompiler verwenden. Das nur zur Klarstellung.Jo stimmt mein Fehler^^
3. Dein Design ist sehr fragwürdig. Die Lesbarkeit wird meiner Meinung nach definitiv nicht erhöht. Schon nur, weil du die Variablen nicht
privatemachst. Du veränderst die Variablen direkt aus anderen Klassen heraus. Dadurch wird es völlig unmöglich irgendwelche Annahmen über die Variablen in der Basisklassen zu machen. Membervariablen sollten so gut wie immerprivatesein.Hmm wahrscheinlich hast du recht, aber ich wollte das trotzdem mal wissen, weil ich dieses Wissen noch in anderen Projekten brauche.
Ok danke
