Abgeleitete Klassen über Basisklassen ansprechen?



  • Hallo,
    mal angenommen, ich hätte eine Klasse, die von einer Basisklasse abgeleitet ist. Wenn ich einen Zeiger auf diese Klasse an eine Funktion übergebe, die die abgeleitete Klasse nicht kennt, aber die die Basisklasse kennt, kann ich dann problemlos Funktionen der abgeleiteten Klasse über die Basisklasse ansprechen?
    Ein Beispiel:

    class OBJECT
    {
    private:
      int x;
    public:
      void setX(int zahl)
      {
        x = zahl;
      }
    
    };
    
    class AOBJECT : OBJECT
    {
    private:
      int xQuadrat;
    public:
      void setX(int zahl)
      {
        x = zahl;
        xQuadrat = zahl*zahl;
      }
    
    };
    
    void xSetzen(void* P_klasse, int x)
    {
      (*OBJECT)P_klasse->setX(x);
    }
    
    void erstellen()
    {
      AOBJECT *P_aobject = new(AOBJECT);
      xSetzen((void*)P_aobject, 5);
    
    }
    

    Ist das prinzipiell möglich und sinnvoll, oder führt das zu Fehlern, oder gibt es bessere Alternativen?

    Danke.



  • Hi,

    das schreit geradezu nach einer virtual-Deklaration:

    class Object
    {
        virtual void Print()
        {
        cout << "Basis";
        }
    }
    class A_Object : public Object
    {
        void Print()
        {
        cout << "Abgeleitet";
        }
    }
    int main()
    {
    Objet* b = new Object();
    A_Object a;
    b->Print;
    b = &a
    }
    
    Ausgabe: BasisAbgeleitet
    

    Das ist sinvoll, und beeinflusst die Laufzeit kaum
    Hintergrund: Der Compiler legt eine Tabelle aus Zeigern auf die Funktionen der Abgeleiteten Klasse an.



  • Läuft das ohne Speicherprobleme? Dann kann ich also tausende abgeleiteter Klassen mit verschiedenen Funktionen in einer Liste speichern, ohne die ganzen Klassen zu kennen? (sofern sie die selben Funktionen verwenden) Ist es sinnvoll, das so zu machen?



  • Hi,

    du kannst alle Klassen der Liste in die gemeinsame Basisklasse konvertieren, und so alle Methonen ansprechen, die auch schon in der Basisklasse deklariert sind.
    #edit#

    das ganze muss über einen Basisklassenzeiger laufen, der auf eine abgeleitete Klasse zeigt (oder auf die Basisklasse), deren Basisklassenmethoden als virtual deklariert sind. Der Compiller wählt sich immer die "passende" Methode aus.



  • Wunderbar, Danke für die Info! Werd ich demnächst mal im größeren Rahmen testen!



  • Mal was anderes:
    Was bringt es, den Zeiger vor dem Funktionsaufruf in void* zu konvertieren, nur um ihn in der Funktion wieder zurückzucasten? 😕



  • Hi,

    Man kann Funktionen programmieren, die mit verschiedenen Dateitypen aufgerufen werden kann. Dies wird in C z.B. in der Funktion Qsort verwendet. In C++ ist das meiner Meinung nicht mehr nötig(Templates, Überladung)



  • @cd9000
    Stimmt, bringt nichts. Ich war mir nur nicht ganz sicher, ob der Compiler einen solchen Typecast akzeptiert.

    @c++eus
    Geht auch, aber was ist eigentlich schneller? Typecast oder Template? Und wie kann ich das mit Templates realisieren?



  • MisterZ schrieb:

    @c++eus
    Geht auch, aber was ist eigentlich schneller? Typecast oder Template? Und wie kann ich das mit Templates realisieren?

    Hi,

    //Template:
    // verwendung: Objekte, für die der >-Operator überladen ist.
    template<class T> T func(T i, T j) {
        if(i < j)
        {
            return j;
        }else return i;
    }
    //Überladung:
    int func(int i, int j) {
        if(i < j)
        {
            return j;
        }else return i;
    }
    double func(double i, double j) {
        if(i < j)
        {
            return j;
        }else return i;
    }
    

    Ich hoffe, das hilft dir...(hab die Überladung noch mit eingebaut.)
    Template ist besser, da Typensicher (und ist void* vorzuziehen.)


Anmelden zum Antworten