Pointer auf Template-Klasse



  • Hallo!

    Das mit den Pointern auf Template-Klassen ist ja an und für sich ganz simpel:

    foo<type_name> * ptr
    

    Wenn ich nun das Template mit unterschiedlichen Typen initialisiere, geht das mit dem Pointer nicht mehr so einfach, dann bin ich doch dazu gezwungen, für den Typ eine Basisklasse zu schreiben, von der dann alle Typen ableiten müssen, mit denen ich das Template initialisiere, so dass das dann wie folgt aussehen müsste:

    class type_base_class {
    ...
    } ;
    
    class derived_type : public type_base_class {
    ...
    } ;
    
    template <class type>
    class foo {
    ...
    } ;
    
    foo<derived_type> instance_of_dt_class;
    
    // DAS ist mir wichtig:
    foo<type_base_class> * ptr = &instance_of_dt_class;
    

    Das muss doch so funktionieren, oder?? Schließlich kann man bei C++ immer Pointer einer Basisklasse auf Instanzen abgeleitete Klassen zeigen lassen... Ist halt nur die Frage, ob das bei Templates auch so geht...



  • //edit verlesen
    also so hab ich das bei mir gelöst:

    //basisklasse
    class Base{
    };
    //abgeleitete Klasse
    template<class T>
    class Derived:public Base{
    };
    //aufruf über pointer
    Base* b=new Derived();
    


  • foo<derived_type> ist doch nicht von foo<type_base_class> abgeleitet.



  • Beispiel:

    template <class type> 
    class foo { 
    public:
       void foo ();
    }; 
    
    template <> 
    class foo<derived_type> { 
    public:
       void kein_foo ();
    };
    

    foo<basis_type> hat ne Methode foo, foo<derived_type> hat keine Methode foo. Was passiert, wenn ich Sie aufrufen will?



  • Wenn ich Templates richtig verstanden habe, geht es nicht so.
    Templates "übernehmen" nicht automatisch die Vererbungshierachie der Typparameter.
    foo<type_base_class> ist deshalb auch nicht eine Basisklasse von foo<derived_type>.

    Du kannst aber Dein Template selbst von einer von einer Basisklasse erben lassen.
    Dann sind alle Instanzen des Templates von dieser Basisklasse abgeleitet. Das ist aber nicht ganz dasselbe, wie Dein Vorschlag.



  • otze schrieb:

    //edit verlesen
    also so hab ich das bei mir gelöst:

    //basisklasse
    class Base{
    };
    //abgeleitete Klasse
    template<class T>
    class Derived:public Base{
    };
    //aufruf über pointer
    Base* b=new Derived();
    

    Bestimmt nicht.
    Wenn dann:

    Base* b=new Derived<Foo>();
    

    Aber das hat Wenig mit dem roblem zu tun.



  • @todo: kannst du mal ein Beispiel dafür bringen, wann du etwas vergleichbares brauchst?



  • oh doch:

    Wenn ich nun das Template mit unterschiedlichen Typen initialisiere, geht das mit dem Pointer nicht mehr so einfach, dann bin ich doch dazu gezwungen, für den Typ eine Basisklasse zu schreiben, von der dann alle Typen ableiten müssen, mit denen ich das Template initialisiere, so dass das dann wie folgt aussehen müsste:

    er ging davon aus, das man die basisklasse als template parameter angeben muss,um sozusagen einen basisklassenzeiger zu bekommen, es ist aber so, dass man direkt den zeiger auf die basisklasse braucht.



  • Helium schrieb:

    @todo: kannst du mal ein Beispiel dafür bringen, wann du etwas vergleichbares brauchst?

    hab ich momentan noch nicht, wollte das mehr so zur allgemeinen information wissen... wenn ichs brauch, sag bescheid 🙂



  • und noch was: mir ging es nicht darum, zeiger auf vererbte klassen zeigen zu lassen, das ist einfach. Es ging mir darum, einen pointer auf eine beliebige instanz einer template-klasse zeigen zu lassen, normalerweise muss man ja einen pointer z.b. mit

    foo<double> * ptr

    deklarieren, bloß dieser ptr kann dann auch nur auf instanzen von foo mit dem template-parameter double zeigen, ich will aber mit meinem ptr auf alle instanzen dieser klasse zeigen -> deshalb muss ich bei der pointer-def. bei foo als template-parameter die basisklasse angeben, von der alle typen, die ich als template-paremeter benutzen will, abgeleitet sind... und einen pointer kann ich ja nicht mit

    foo<> * ptr

    definieren, oder??



  • nochmal:

    Foo<X> hat nichts mit Foo<Y> zu tun. Es kann föllig andere Methoden etc. Enthalten.

    Es kann also sein, das

    Foo<int> foo_int;
    
    foo_int.methode (); // hierum geht's
    

    ein legales Konstrukt ist, während

    Foo<double> foo_double;
    
    foo_double.methode (); // hierum geht's
    

    illegal ist, weil in Foo<int> eine Methode 'methode' definiert ist, in Foo<double> aber nicht. Das gleiche gilt für Foo<Base> und Foo<Derived>. Foo<Derived> kann ganz anders spezialisiert sein, also ein komplett anderes Interface besitzen, andere Basisklassen haben, ... . Foo<Base> und Foo<Derived> sind zwei völlig Verschiedene Typen, die in etwa so viel gemein haben, wie 'int' mit 'std::setstd::string'.

    Du kannst aber alle Foo<...> von einer gemeinsamen Basis ableiten, wie otze es gezeigt hat und einen Zeiger dieses Typs verwenden.



  • nein! die typen, die ich dann einsetzen will, müssen alle von einer basisklasse abgeleitet sein und somit haben sie alle bestimmte funktionen, wenn ich dann spezifische funktionen benutzen will, muss ich halt zum abgeleiteten typ casten... es geht mir nicht darum, einen pointer auf foo mit int und double zu schreiben, das geht natürlich nicht, aber auf klassen, die von einer gemeinsamen basis ableiten



  • nein, das funktioniert nich...



  • @todo: Entweder versteh ich dich absolut nicht oder du hast Templates vom Prinzip her noch nicht verstanden:

    // Eine Hirarchie
    class Basis {};
    class Derivat1 : public Basis {};
    class Derivat2 : public Basis {};
    
    // Das Template:
    
    template <typename T>
    class Foo {
    public:
       void methode ()
       { cout << "Hallo"; }
    };
    
    template <>
    class Foo<Derivat2> {
    public:
       int x;
    };
    
    int main ()
    {
       Foo<Derivat1> d1;
       Foo<Derivat2> d1;
    
       d1.methode();  // legaler Aufruf
       d1.x;          // x nicht in Foo<Derivat1> definiert
    
       d2.methode();  // methode nicht in Foo<Derivat2> definiert
       d2.x;          // legaler aufruf
    }
    

    Angenommen man könnte jetzt schreiben:

    Foo<Basis> * foo = new Foo<Derivat2>;
    

    Was würde bei foo->methode() passieren? Eine solche Methode existiert nicht. Sie wird auch nicht geerbt (von wem denn).


Anmelden zum Antworten