Methode ersetzen / überlagern



  • Moin,
    ich glaube ich habe ein Brett vorm Kopf. Auf jeden Fall komme ich nicht weiter.
    Ich habe eine Klasse A in der es viele Methoden gibt die irgendwo die Methode tueDies(...) aufrufen.
    Ich brauche die Klasse A jetzt mit einer anderen Methode tueDies(...). Daher dachte ich es wäre das Einfachste A zu erben und tueDies() zu überschreiben:

    Beispiel:

    class A {
    public:
       A(){
          ...
          tueDies();
       }
    
       void tueDies(){
          cout << "A";
       }
    }
    
    class B : public A {
       B(...):A();
    
       void tueDies(){
          cout << "B";
       }
    }
    

    Wenn ich jetzt ein Objekt B erstelle wird A ausgegeben (gewünscht ist B). Wie schaffe ich es, dass die geerbten Methoden die überschriebene Methode aufrufen ohne Klasse A zu ändern? Das Problem ist, dass Klasse A sehr komplex ist. Es gibt > 100 Aufrufe von tueDies() in verschiedenen Methoden und Konstruktoren, so dass eine Überschreibung dieser keinen Sinn macht.

    Vielen Dank für eure Hilfe



  • Wenn Du einen A-Zeiger(o. Referenz) verwendest mußt Du die Methode virtual machen.
    Oder Du verwendest ein echtes B-Objekt:
    `B b;

    b.tuWas();

    `



  • Ich dachte ich verwende ein echtes Objekt B:

    B * beispiel = new B(...);
    

    Die Methoden werden nur intern aufgerufen. Gestartet durch einen Methodenaufruf im Konstruktor von A.



  • osfriese schrieb:

    Ich dachte ich verwende ein echtes Objekt B:

    B * beispiel = new B(...);
    

    Die Methoden werden nur intern aufgerufen. Gestartet durch einen Methodenaufruf im Konstruktor von A.

    Wenn Du's aus einem A rufst:
    B::tuwas();

    Edit: Wobei ich glaube, daß das im Konstruktor von A nicht funktionieren kann, da das B dort noch nicht existiert...



  • Vielen Dank!
    Die Methode in Klasse A virtual zu setzen funktioniert.
    Gibt es noch eine Möglichkeit das gleiche zu erreichen ohne Klasse A anzufassen?



  • osfriese schrieb:

    Die Methode in Klasse A virtual zu setzen funktioniert.

    Das glaube ich dir nicht so ganz. Mit dem Funktionsaufruf im Konstruktor von A kannst du gar nicht die Funktionen von Klasse B (ohne unsichere Hacks)* aufrufen, da zu diesem Zeitpunkt die Klasse B noch gar nicht erstellt wurde. Genausowenig ist klar ob gerade überhaupt ein B Objekt erstellt wird oder was anderes das auch von A erbt. Außerhalb des Konstruktors kannst du in Klasse A aber schon Funktionen von B aufrufen wenn die Funktion in Klasse A als virtual gekennzeichnet ist. Ohne etwas in A zu verändern geht es nicht.

    *Tatsächlich fällt mir eine halbwegs sichere Methode mit Templates ein, aber das erwähne ich hier erstmal nicht, da du dich erstmal um Grundlagen kümmern solltest.



  • Caligulaminus schrieb:

    Edit: Wobei ich glaube, daß das im Konstruktor von A nicht funktionieren kann, da das B dort noch nicht existiert...

    Richtig, funktioniert nicht.
    Der Standard definiert das so.

    Wobei es der Standard auch genau so gut anders hätte definieren können. In C# wird z.B. immer die Methode des "most derived type" aufgerufen, also in diesem Fall immer B.
    (Was in C# weniger problematisch ist, weil man sich zumindest darauf verlassen kann dass alle Member "zero-initialized" worden sind bevor der erste Konstruktor anfing zu laufen (k.A. wie "zero-initialized" in C# korrekt heisst, aber ich denke es ist klar was ich meine). Bzw. werden auch Field-Initializer ausgeführt bevor irgend ein Ctor anfängt zu laufen.).


Anmelden zum Antworten