Eigenschaften von Basisklassen innerhalb von Templates erben
-
templates schrieb:
CStoll schrieb:
Die globale Klasse "Impl" hat absolut gar nichts mit "Abstrakt" zu tun (außer daß sie ein paar gleichnamige Methoden hat).
Danke für die schnelle Hilfe.
Impl soll die Implementierung sein.
Abstakt soll die abstrakte Basisklasse darstellen.Dann wäre es auch gut, dem Compiler diesen Zusammenhang mitzuteilen
(idR durch Vererbung)CStoll schrieb:
Und bei der Vererbung mußt du natürlich angeben, von welcher Version der Basisklasse du ableiten willst, also
class Impl : public Abstract<DatenTyp> {...}.wenn ich
class Impl : public Abstract<DatenTyp> {...}statt
class Impl : public Abstract{...}verwende, dann bekomme ich diesen Fehler
error C2143: syntax error : missing ',' before '<'wahrscheinlich weil ich Impl schon mit einem Template Parameter initialisiere?
Ist denn die Klasse Abstrakt an der Stelle bekannt, wo du sie verwenden willst?
-
CStoll schrieb:
Ist denn die Klasse Abstrakt an der Stelle bekannt, wo du sie verwenden willst?
Shit ich merke dass ich nicht aufgepasst habe:
template<typename A,typename B, typename DatenTyp> class Base { private: // A : Abstract, B : Impl class B: public A{ }; public: Base(const shared_ptr<DataType> &data) : B(data) { ... } }
-
Nein, so kann das nicht funktionieren, weil es da Mehrdeutigkeiten beim Bezeichner B gibt (ich bin mir bei den Regeln nicht ganz sicher, aber entweder der Parameter und der innere Typ landen im selben Scope oder letzterer überdeckt den Parameter). Was willst du mit der ganzen Geschichte eigentlich erreichen?
PS: Wenn es dir darum geht, zwischen den voneinander unabhängigen Klassen Abstrakt und Impl nachträglich eine Vererbungsbeziehung zu erzeugen - das ist in C++ nicht möglich.
-
CStoll schrieb:
PS: Wenn es dir darum geht, zwischen den voneinander unabhängigen Klassen Abstrakt und Impl nachträglich eine Vererbungsbeziehung zu erzeugen
Besser könnte man meinen Wunsch nicht beschreiben.
CStoll schrieb:
- das ist in C++ nicht möglich.
Wie könnte man es sonst angehen. Ich habe fertige abstrakte Basisklassen die im Prinzip auf mehrere Implementierungsklassen passen. Bisher habe ich es normal gelöst.
-
Normalerweise verwendet man dazu direkte Vererbung, wenn man die betroffenen Klassen schreibt. Wenn die Klasse X die von Interface/Basisklasse Y vorgegebenen Methoden definiert, zeigt sie das, indem sie öffentlich von Y abgeleitet wird (wenn sie mehrere Interfaces unterstützt, ergibt sich entsprechend eine Mehrfachvererbung).
-
templates schrieb:
CStoll schrieb:
Ist denn die Klasse Abstrakt an der Stelle bekannt, wo du sie verwenden willst?
Shit ich merke dass ich nicht aufgepasst habe:
template<typename A,typename B, typename DatenTyp> class Base : public A, public B { public: Base(const shared_ptr<DataType> &data) : B(data) { ... } }nicht einmal dass funktioniert. Er schreibt das die Methoden a() und b() abstrakt sind obwohl ich auch von B ableite und dort alles implementiere?!?
Da muss doch was möglich sein..
-
Sorry habe in der letzten Nachricht falsch gepastet..
-----------------------------------------------------template<typename A,typename B, typename DatenTyp> class Base : public A, public B { public: Base(const shared_ptr<DataType> &data) : B(data) { ... } }nicht einmal dass funktioniert. Er schreibt das die Methoden a() und b() abstrakt sind obwohl ich auch von B ableite und dort alles implementiere?!?
Da muss doch was möglich sein..
-
Ich habe mal das Problem in einen großen Codeschnipsel zusammengefasst. Vielleicht weiß ja jemand wie man es doch umgehen kann:
template < typename Abstract , typename Impl , typename DataType > class Base : public Abstract, public Impl { DataType mpData; public: void run() { std::cout << "Im Base"; } }; template<typename DataType> class Abstract { public: virtual void a() = 0; }; template<typename DataType> class Impl { public: void a() { std::cout << "Im Impl"; } }; int main(int argc, char** argv) { Base<Abstract<double>,Impl<double>,double> temp; temp.a(); return 0; }Die Fehlermeldung sieht so aus:
1>c:\temp\test.cpp(29): error C2259: 'Base<Abstract,Impl,DataType>' : cannot instantiate abstract class 1> with 1> [ 1> Abstract=Abstract<double>, 1> Impl=Impl<double>, 1> DataType=double 1> ] 1> due to following members: 1> 'void Abstract<DataType>::a(void)' : is abstract 1> with 1> [ 1> DataType=double 1> ] 1> c:\temp\test.cpp(16) : see declaration of 'Abstract<DataType>::a' 1> with 1> [ 1> DataType=double 1> ] 1>c:\temp\test.cpp(31): error C2385: ambiguous access of 'a' 1> could be the 'a' in base 'Abstract<double>' 1> or could be the 'a' in base 'Impl<double>' 1>c:\temp\test.cpp(31): error C3861: 'a': identifier not found
-
Warum versuchst du eigentlich hier krampfhaft statische und dynamische Polymorphie unter einen Hut zu bringen?
Entweder du templatisierts und nutzt einfach die Funktionen die du brauchst:
template <typename T> class Base{ public: void a(){ T().a(); } };Oder aber du nutzt die Vererbung voll aus:
class Abstract { public: virtual void a() = 0; } class Impl1 : Abstract { virtual void a() { cout << "Impl1"; } }; class Impl2 : Abstract { virtual void a() { cout << "Impl2"; } }; class Base { public: Base(Abstract& a) : a(a) {} void run() { a.a(); } private: Abstract& a; }Die Aufrufe und Ausgaben kannste dir ja selber überlegen.
-
bmario schrieb:
Warum versuchst du eigentlich hier krampfhaft statische und dynamische Polymorphie unter einen Hut zu bringen?
Weil man sich praktisch alle zwischenklassen sparen kann. Bei m-Basisklassen und n-Implementierungen macht es schon Sinn sich zu überlegen ob man es nicht doch irgendwie hinkriegt.
-
Klingt nach Variante 1: Mach's mit Temples.
struct Abstract1 { virtual void a() = 0; }; struct Abstrct2 { virtual void a() = 0; }; struct Impl1 : Abstract1 { virtual void a() { cout << "Impl1";} }; struct Impl2 : Abstract2 { virtual void a() { cout << "Impl2";} }; template<typename Abstract> class Base { public: Base(Abstract& impl) : impl(impl) {} void run() { impl.a(); } private: Abstract& impl; };