Vererbung und (Down)Casting

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Vererbung und (Down)Casting

    Hallo,
    ich versuche zur Zeit, eine Hierarchie von Klassen für eine API zu erstellen und komme vom Wechsel Java->C++ (trotz diverser Bücher) noch ins stolpern- vielleicht kann mir jemand weiterhelfen.

    Beispiel: Es soll drei Klassen geben:
    - Person
    - Wissenschaftler (erbt von Person)
    - Professor (erbt von Wissenschaftler)

    Person hat als Attribute:
    - eine int-variable: int userid;
    - Eine Zeigervariable: IrgendeineKlasse *zeiger;

    Die Klassen unterscheiden sich im wesentlichen nur dadurch, dass neue Funktionen hinzukommen- die Attribute bleiben immer gleich. Die Klassendeklarationen sehen in etwa wie folgt aus:

    class Person {
    public:
    Person(const int &id, IrgendeineKlasse &derZeiger);
    virtual ~Person();
    protected:
    int userid;
    IrgendeineKlasse *zeiger;
    }

    class Wissenschaftler : public Person {
    public:
    Wissenschaftler(const int &id, IrgendeineKlasse &derZeiger);
    }

    class Professor : public Wissenschaftler {
    public:
    Professor (const int &id, IrgendeineKlasse &derZeiger);
    }

    Die Konstruktoren rufen jeweils ihre Basisklasse auf, also z.B.

    Professor::Professor(const int &id, IrgendeineKlasse &derZeiger) : Wissenschaftler(id, derZeiger) {}

    Soweit so gut (?). Nun möchte ich alle diese Personen, Wissenschaftler und Professoren in einem Vektor verwalten. Da Person die Wurzelklasse ist, deklariere ich also einen Vektor:

    vector<Person> liste;

    In diese Liste kann ich nun ohne Probleme Personen, Wissenschaftler und Professoren ablegen:

    liste.push_back(Professor(37, foo));

    In Java hätte ich nun kein Problem damit zu sagen:

    Professor prof = (Professor)liste[3]; // Ich weiss, dass dort ein Prof steht

    Der Compiler vermisst für den Cast aber einen Konstruktor für:

    Professor(Person&)

    Schreibe ich so einen Konstruktor kommt die Fehlermeldung, dass Person nicht die Basisklasse von Professor ist (sondern Wissenschaftler natürlich).

    Wie kann man das elegant in C++ lösen? Ich mache mir zudem sorgen, dass bei komplexeren Vererbungshierarchien der Prozessor nur noch damit beschäftigt ist, sich an Konstruktor-Aufrufen entlang zu hangeln.

    Könnte mir dazu jemand einen Tipp geben?

    Viele Grüße,

    Peter
  • Da du vector<Person> hast, werden alle Objekte von abgeleiteten Klassen gesliced, dh im Endeffekt enthält dein Vektor keinen Professor, sondern nur eine Person. Alle professor-spezifischen Daten sind verloren. Deshalb kannst du daraus auch keinen Professor mehr machen mit Professor(Person&). Umwandlungen dieser Art könnten mit einem dynamic_cast<Professor*> funktionieren.
    Eine Lösung wäre wohl, wenn du einen vector<Person*> machst. Dann legst du Professoren-Objekete an und speicherst nur mehr den Basis-Ptr auf sie.
    Ausserdem immer beachten, dass vector keine Speicherverwaltung übernimmt. Dh wenn man vector<Person*> hat, dann muss man ggfs die Objekte im Vektor selbst mit delete löschen.
    Zum casten von Pointern innerhalb Vererbungshierarchien hilft dir das evtl:
    http://web.mit.edu/sunsoft_v5.1/www/c-plusplus/c++_ug/Cast.new.doc.html
    Die Beschäftigung des Prozessors mit Konstrukor-Aufrufen ist idR kein Problem, virtuelle Funktionen schon eher, das kostet mehr Laufzeit. Aber Konstruktorenaufrufen sollten mWn relativ schnell gehen. Ausserdem sollte man wohl eh besser nicht Vererbungen über 5 Ebenen oder so aufbauen ;)