[gelöst] Verständnisproblem mit virtual



  • Hallo,

    ich hab bei virtual gelesen, dass es den Compliler anweist immer die Funktion aus der zugehörigen Klasse zu nehmen. Und das klappt nur, wenn es über Pointer aufgerufen wird.
    Folgendes habe ich programmiert: (hier kurz als Schema)

    class A
    {
    protected:
      int whoami;
    public:
      A();
      A(int m_type);
      virtual void ShowMe();
    }
    
    class B : public A
    {
      B();
      B(int m_type);
      virtual void ShowMe();
    }
    
    A::A() {whoami = 0; ShowMe(); }
    A::A(int m_type) {whoami = m_type; ShowMe(); }
    A::ShowMe() { cout << "Von A: " << whoami; }
    
    B::B() : A() {}
    B::B(int m_type) : A(m_type) {}
    B::ShowMe() { cout << "Von B: " << whoami; }
    

    Es passiert natürlich noch viel mehr in meiner Klasse, aber das ist der wesentliche Problemteil.

    main()
    {
      A* pMeins = new B(1); // Ausgabe: "Von A: 1"
      delete pMains;
    }
    

    Wenn ich virtual richtig verstanden habe, dann müsste doch dort "Von B: 1" stehen und nicht "Von A: 1", oder? Denn die Funktion ShowMe() ist virtual.

    Was verstehe ich falsch?
    Danke,
    Stefan



  • ich hab bei virtual gelesen, dass es den Compliler anweist immer die Funktion aus der zugehörigen Klasse zu nehmen. Und das klappt nur, wenn es über Pointer aufgerufen wird.

    Auch bei Referenzen funnktionierts.

    Du darfst die virtuellen Methoden erst Aufrufen, wenn das Objekt vollständig konstruiert ist. Konkret: Wenn bei Dir A konstruiert ist, und Du ShowMe() aufrufst, gibt es B noch gar nicht.

    Simon

    Edit: z.B. so:

    main() 
    { 
      A* pMeins = new B(1); // Ausgabe: "Von A: 1" 
      pMeins->ShowMe();
      delete pMains; 
    }
    


  • Danke schön,
    das erklärt natürlich warums nicht so läuft wie ich das will.



  • stefanjann schrieb:

    ich hab bei virtual gelesen, dass es den Compliler anweist immer die Funktion aus der zugehörigen Klasse zu nehmen. Und das klappt nur, wenn es über Pointer aufgerufen wird.

    Rufe niemals virtuelle Funktionen aus Konstruktoren auf (es sei den du bist der Konsequenzen wirklich bewusst).

    In Vererbungshierarchien wird immer zuerst von der Basisklasse aus die Konstruktoren ausgeführt. In deinen Beispiel wird bei einer Erstellung einer Klasse B, erst der A-Anteil konstruiert, dann der B-Anteil. Somit "sieht" der Konstruktor nur die A-Umsetzung der virtuellen Funktion.



  • die virtuelle funktion der basis klasse muss in der abgeleiteten klasse gleich heißen!

    Und in deiner main-Methode ist ja doch gar kein Aufruf der ShowMe()-Methode über den Pointer deiner Basisklasse A.
    Du rufst ShowMe auch in der Klasse A auf.
    1. nimmt er dann die eigene Klassenmethode, also aus A.
    2. (wahrscheinlich, was du möchtest) kennt die Klasse A doch gar nicht die Funktion der Klasse B! Selbst mit dem Scope-Operator der Klasse B würdest du einen Fehler bekommen.

    (leider ohne cpp-tags)

    class A{
    virtual void showme();
    };

    class B : public A{
    void showme();
    }
    -------------------------------------

    B myB();

    A *myA = &myB;
    myA->showme();

    Ich hoffe, ich konnte dir auf die schnelle helfen 😉
    Ansonsten google mal nach Polymorphimus.

    Gruß Sdy


Anmelden zum Antworten