Vererbung, Konstruktor der Subklasse aufrufen



  • Hi,
    habe so ein Problem mit einer Aufgabenstellung in der Uni.
    Es gibt zwei Klassen: Person und Patient. Patient erbt dabei von Person.

    In main soll später ein Objekt von Patient erstellt werden.
    Anschließend ein Objekt von Person, welches mit dem Patient-Objekt erstellt wird.

    So wie ich das sehe, soll also die Oberklasse Person einen Konstruktor enthalten, der als Parameter die Subklasse enthält. Ist sowas überhaupt möglich?
    Habe jetzt mehrere Versuche gemacht und komme nicht voran.

    Hier mal mein letzer Versuch...

    #include <iostream>
    #include <string>
    
    using std::cout;
    using std::endl;
    using std::string;
    
    class Person;
    class Patient;
    
    class Person{
      public:
        string name;
        Person(string n) : name(n) {}
        // Person(Patient pa) {}     funktoniert nicht
    };
    
    class Patient : Person {
      public:
        int nummer;
        Patient(string n, int nr) : Person(n), nummer(nr) {};
    };
    

    Die main sieht später ungefähr so aus:

    int main(){
      Patient pat("Peter", 521);
      Person pers(pat);
    
      return 0;
    }
    

    Kurzfassung: Kann eine Oberklasse einen Konstruktor mit Parameter Subklasse enthalten. Wenn ja wie implementieren?

    Hoffe ihr erkennt meint Problem und könnt mir helfen.

    Thx Magnus



  • Du musst einen copy-constructor in Person definieren. Der implizite Up-Cast macht den Rest.

    Person(Person const& p):
        name(p.name) {}
    


  • Sone schrieb:

    Du musst einen copy-constructor in Person definieren.

    Er braucht das nicht, das passiert implizit.


  • Mod

    Bist du sicher, dass du hier private-Vererbung möchtest? Das soll doch wohl sicherlich

    class Person{
      public:
        string name;
        Person(string n) : name(n) {}
    };
    
    class Patient : public Person {
      public:
        int nummer;
        Patient(string n, int nr) : Person(n), nummer(nr) {};
    };
    

    sein. Und dann funktioniert das schon, solange du nicht irgendwelche speziellen Aktionen durchführen willst, falls ein Patient als Argument benutzt wird. Ein Patient ist schließlich auch eine Person und kann daher in Kontexten wo eine Person erwartet wird (hier: der (automatisch erstellte) Kopierkonstruktor von Person) als Person benutzt werden. Dabei verliert er jedoch alle Eigenschaften des Patienten und ist nur noch eine Person (Stichwort: splicing).

    ICh nehme an, das obige ist das, was du haben möchtest. Falls du noch einen speziellen Patientkonstruktor möchtest, dann geht das so:

    class Person{
      public:
      string name;
      Person(string n) : name(n) {}
      Person(const Person& other);
      Person(const Patient& other);
    
    };
    
    class Patient : public Person {
      public:
        int nummer;
        Patient(string n, int nr) : Person(n), nummer(nr) {};
    };
    
    Person:: Person(const Person& other): name(other.name) { cout << "Person mit Person initialisiert\n" ;}
    
    Person::Person(const Patient& other): name(other.name) { cout << "Person mit Patient initialisiert\n" ;}
    

    Und falls du tatsächlich private-Vererbung möchtest, dann geht das nach dem gleichen Schema.



  • Ah okay danke. Stichwort Copy-Konstrukor ist vermerkt 🙂



  • apkast schrieb:

    Sone schrieb:

    Du musst einen copy-constructor in Person definieren.

    Er braucht das nicht, das passiert implizit.

    Ja, da war ein Denkfehler!
    Ich hatte die implizite Generierung von Copy-Ctoren falsch im Kopf.
    Aber der Standard verschafft Klarheit :xmas1:

    If the class definition does not explicitly declare a copy constructor, one is declared implicitly.



  • Sone schrieb:

    Ich hatte die implizite Generierung von Copy-Ctoren falsch im Kopf.

    Das sind absolute Grundlagen, wie kann man das nicht wissen 😮



  • Ach das kann man schnell übersehen/verwechseln wenn man zu sehr damit beschäftigt ist anderen ihre Fehler aufzuzeigen oder generell unerwünschten Quark zu schreiben.



  • hustbaer schrieb:

    Ach das kann man schnell übersehen/verwechseln wenn man zu sehr damit beschäftigt ist anderen ihre Fehler aufzuzeigen oder generell unerwünschten Quark zu schreiben.

    :xmas1: 👍



  • Magnus667 schrieb:

    In main soll später ein Objekt von Patient erstellt werden.
    Anschließend ein Objekt von Person, welches mit dem Patient-Objekt erstellt wird.

    Sicher, dass du das richtig verstanden hast? Vielleicht sollst du ja auch nur mit einem Person-Zeiger arbeiten, der auf ein Patient-Objbet zeigt. So, wie du das gedacht hast, wäre das Slicing und ich finde das ein bisschen komisch, dass hier Slicing erwünscht sein soll.

    Man benötigt übrigens keinerlei solcher Copy-Konstruktoren selbst schreiben in diesem Fall; denn Slicing ist so auch schon möglich:

    struct Person
    {
      std::string name;
    
      explicit Person(std::string nam)
      : name(nam)
      {}
    };
    
    struct Patient : Person
    {
      int nummer;
    
      Patient(std::string nam, int nr)
      : Person(nam), nummer(nr)
      {}
    };
    
    void wieduheisst(Person const& p)
    {
      std::cout << p.name << std::endl;
    }
    
    int main()
    {
      Patient pat ("Hans",1729);
      Person *p = &pat; // Vielleicht ist es das, was du machen sollst
      Person q = pat; // Slicing, der Person-Teil von pat wird kopiert.
    
      wieduheisst(pat);
      wieduheisst(*p);
      wieduheisst(q);
    }
    


  • Sone schrieb:

    Du musst einen copy-constructor in Person definieren.

    apkast schrieb:

    Er braucht das nicht, das passiert implizit.

    Ja, da war ein Denkfehler!
    Ich hatte die implizite Generierung von Copy-Ctoren falsch im Kopf.

    apkast schrieb:

    Das sind absolute Grundlagen, wie kann man das nicht wissen 😮

    hustbaer schrieb:

    Ach das kann man schnell übersehen/verwechseln wenn man zu sehr damit beschäftigt ist anderen ihre Fehler aufzuzeigen oder generell unerwünschten Quark zu schreiben.

    :xmas1: 👍

    👍 👍 thx, ymmd! again!


Anmelden zum Antworten