Eigenschaften von Basisklassen innerhalb von Templates erben



  • 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;
    };
    

Anmelden zum Antworten