next up previous contents index
Next: Virtuelle Funktionen Up: Klassen-Hierarchien und Vererbung Previous: Konstruktion und Destruktion

Typanpassung

  Ein Objekt einer abgeleiteten Klasse kann einem Objekt (einer) seiner Basisklasse(n) ohne explizite Typkonvertierung zugewiesen werden:

    uhr tschibo;
    wecker radio;
    tschibo = radio; 
    // OK, jeder Wecker ist eine Uhr

Andersrum gilt dies nicht:

    uhr kirchturm;
    wecker hahn;
    hahn = kirchturm; 
    // NEIN, eine Uhr ist i.a. kein Wecker.

Die gleichen Reglen gelten auch für Zeiger und Referenzen:

   base b;
   deriv d;
   base *pb = &d;   // OK
   base &rb = &d;   // OK
   deriv *pd = &b;  // FEHLER
   deriv &rd = &b;  // FEHLER

Will man auf Elemente der abgeleiteten Klasse über ein Objekt der Basisklasse oder einen Zeiger oder eine Referenz auf die Basisklasse zugreifen, braucht man eine explizite Konvertierung:

  wecker w(11,30,7,15);  // ein Wecker.
  uhr *uhrzeiger = &w;   // OK.

  uhrzeiger->show();  
            // das ist NICHT wecker::show !!
  ((wecker*)uhrzeiger)->show();  
            // so ist's richtig!

Wie kann man im Allgemeinfall (z.B. eine Liste von uhr-Zeigern) sicherstellen, daß bei Pointerzugriff auf die richtigen Klassenelemente zugegriffen wird ???

1.
Man verweist nur auf einen Typ (uhrzeiger zeigt immer auf uhr). Unbefriedigend!
2.
Man baut ein Typfeld in die Basisklasse ein. Konstruktoren setzen diese Feld. Funktionen lesen es. Fehleranfällig!
3.
Man verwendet virtuelle Funktionen. Ideal!

Benutzer-definierte Typfelder

  Ein Beispiel zum Lösungsvorschlag 2.:

    class uhr
    { int std;
      int min;
    public:
      enum uhrtyp { u, w };
      uhrtyp ut;
      uhr(int s, int m) 
            : std(s), min(m), ut(u) {};
      uhr() : std(0), min(0), ut(u) {};
      void show();
    };
    class wecker : public uhr
    { public:
      uhr alarmzeit;
      wecker() : alarmzeit(0,0) {ut=w;}
      wecker(int s, int m, int as, int am) 
               : uhr(s,m), 
                 alarmzeit(as,am){ ut=w;}
    };
    void uhr::show() 
    { cout << std << ':' << min;
      if (ut == w)
      { wecker *w = (wecker*)this;
        cout << " || ";
        w->alarmzeit.show();
      }
    }

Diese Methode ist besonders bei größeren Programmen fehleranfällig:


next up previous contents index
Next: Virtuelle Funktionen Up: Klassen-Hierarchien und Vererbung Previous: Konstruktion und Destruktion

Peter Pfahler, 1997