Fragen zur Vererbung



  • Guten Tag,

    ich habe ein Problem mit der Vererbung einer Klasse und hoffe das mir jemand helfen kann.

    Es geht um folgende Aufgabenstellung:

    Ich habe eine Basisklasse: Bauteil

    Diese ist definiert und implementiert. Nun soll ich eine Kindklasse: Kondensator, defnieren und implementieren.

    gegeben sind die Konstruktoren:

    Kondensator(); 
    Kondensator(double nWert, string nName);
    

    und die Einheit soll als feste Zeichenfolge "F" haben.

    ebenfalls sind die Funktionen

    void Parallel(Kondensator P1);
    static Kondensator Seriell(Kondensator P1, Kondensator P2, string nName);
    

    von der Klasse Bauteil ist folgendes vorhanden:

    class Bauteil
    {
         private:
           string Name;
         protected:
           double Wert;
           string Einheit;
         public:
           Bauteil();
           Bauteil(double nWert, string nEinheit, string nName);
           void set_Name(string nName);
           string get_Name();
           void Drucken();
    };
    

    und die Implementierung:

    Bauteil::Bauteil()
    {
      Wert = 0;
      Einheit = "n.d.";
      Name = "n.d.";
    }
    
    Bauteil::Bauteil(double nWert, string nEinheit, string nName)
    {
        Wert = nWert;
        Einheit = nEinheit;
        Name = nName;
    }
    void Bauteil::set_Name(string nName) { Name = nName; }
    
    string Bauteil::get_Name() { return Name; }
    
    void Bauteil::Drucken()
    {
        cout << Name << "(" << Wert << " " << Einheit << ")" << endl;
    }
    

    Nun zum Problem:

    Es soll der Klassenprototyp der Klasse Kondensator erstellt werden, sowieo die Implementierung der Konstruktoren.

    Meine "Lösung":

    class Kondensator : public Bauteil
    {
       privat:
         string Name;    //richtig? Da "string Name" der Mutterklasse ja privat?
       public:
         Kondensator();    //standardkonstruktor
         Kondensator(double nWert, string nName); //überl. Konsrukt.
         void Parallel(Kondensator P1); //methoden
         satic Kondensator Seriell(Kondensator P1, Kondensator P2, string nName);
    }
    

    nun die Implementierung:

    Kondensator::Kondensator()
                :Bauteil(Wert, Einheit)  //richtig? diese werden ja übergeben
    {
       name="n.d"; //nicht definiert
       Einheit='F'; //laut aufgabenstellung soll die Einheit ja F sein
       Wert=0;    // wie vorher bereits
    }
    
    Kondensator::Kondensator(double nWert, string nName)
                :Bauteil(Wert, Einheit)  //richtig? diese werden ja übergeben
    {
      Name=nName;
      Wert=nWert;
      Einheit='F';
    }
    

    Ist das so richtig? Wird von der Klasse Bauteil nur der "protected" Inhalt vererbt?

    Ich habe zwar Übungsbeispiele und den Erlenkötter, komme aber einfach nicht vorran.

    Vielen Dank für eventuelle Hilfe. 🙂



  • AntonC++ schrieb:

    Meine "Lösung":

    privat:
         string Name;    //richtig? Da "string Name" der Mutterklasse ja privat?
    

    Nein, nicht richtig. Die Elternklasse hat schon ein Namensattribut, auf das du zwar keinen direkten Zugriff hast, aber das macht nichts. Dafür sind die setter und getter da.

    nun die Implementierung:

    Kondensator::Kondensator()
                :Bauteil(Wert, Einheit)  //richtig? diese werden ja übergeben
    

    Nein, da wird nichts übergeben. Kondensator::Kondensator() hat keine Argumente. Das sollte dir dein Compiler auch sagen, dass Wert und Einheit nicht definiert sind.

    {
       name="n.d"; //nicht definiert 
       Einheit='F'; //laut aufgabenstellung soll die Einheit ja F sein
       Wert=0;    // wie vorher bereits
    }
    

    die Attribute sind alle Teil der Elternklasse und sollten über deren Konstruktor gesetzt werden. In Kondensator hast du da keinen Zugriff drauf.

    Kondensator::Kondensator(double nWert, string nName)
                :Bauteil(Wert, Einheit)  //richtig? diese werden ja übergeben
    

    falsch. Bauteil hat keinen Konstruktor mit zwei Argumenten.

    {
      Name=nName;
      Wert=nWert;
      Einheit='F';
    }
    

    siehe oben.

    Ist das so richtig? Wird von der Klasse Bauteil nur der "protected" Inhalt vererbt?

    Vererbt wird alles. Zugreifen kann die abgeleitete Klasse nur auf protected und public Member.

    Ich habe zwar Übungsbeispiele und den Erlenkötter, komme aber einfach nicht vorran.

    Die Übungsbeispiele bringen dir nicht viel, weil du offenbar die grundlagen noch nicht wirklich verinnerlicht hast. Lies dir die entsprechenden Kapitel im buch deiner Wahl nochmal ausführlich durch (und zwar so, dass du sie verstehst).



  • Die Basisklasse übergibt mir ja alle Werte, Kondensator hat so gesehen keine "Neuen".

    Sprich, die Definition wäre

    class Kondensator : public Bauteil
    {
        private:
          //leer
        public:
          Kondensator();
          Kondensator(double nWert, string nName);
          void Parallel(Kondensator P1);
          static Kondensator Seriell(Kondensator P1, Kondensator P2, string nName);
    }
    

    Dieser Teil müsste dann so stimmen?



  • Servus Anton,
    wie ich deinem Beitrag entnehme schreibst du morgen auch die Klausur in C++?
    Hast du nähere Infos zu den Klausurthemen?
    Wäre nett, wenn du antwortest.
    Grüße



  • AntonC++ schrieb:

    Die Basisklasse übergibt mir ja alle Werte, Kondensator hat so gesehen keine "Neuen".

    Sprich, die Definition wäre

    class Kondensator : public Bauteil
    {
        private:
          //leer
        public:
          Kondensator();
          Kondensator(double nWert, string nName);
          void Parallel(Kondensator P1);
          static Kondensator Seriell(Kondensator P1, Kondensator P2, string nName);
    }
    

    Dieser Teil müsste dann so stimmen?

    1. Welchen Sinn haben die leeren Konstruktoren in Kondensator und Bauteil? Defekte Bauteile willst du damit ja eher nicht simulieren
    2. 2 parallel oder seriell vorschaltete Kondensatoren sind kein Kondensator oder ein anders Bauteil. Da stimmt etwas mit deiner Programmlogik nicht


  • @Malle

    Guten Tag Herr ....,

    vor diesem Klausurtermin habe ich kein Tutorium zu Programmieren II angeboten. Grundsätzlich empfehle ich Ihnen, die altel Klausuraufgaben als Vorbereitung zu bearbeiten. Ansonsten wird diese Klausur einen ähnlichen Aufbau wie die alten Klausuren haben.

    Viel Erfolg!

    Freundliche Grüße,
    ....

    Die Konstruktoren und Methoden sind so vorgegeben, sehe den Sinn ebenfalls nicht.

    Man soll halt den Klassenprotoyp von Kondensator aufschreiben und die Konstruktoren implementieren...

    wäre dann die Implementierung einfach:

    Kondensator::Kondensator()
    { } // ?
    

    und

    Kondensator::Kondensator(double nWert, string nName)
                    :Bauteil(nWert, nEinheit, nName)
    { // und dann? Was muss ich an dieser Stelle beachten?
    


  • AntonC++ schrieb:

    wäre dann die Implementierung einfach:

    Kondensator::Kondensator()
    { } // ?
    

    Dann wäre der Name und die Einheit "n.d.", weil du (implizit) den default-Ctor von Bauteil aufrufst. Die Einheit soll für Kondensatoren aber grundsätzlich "F" sein, wenn ich die Aufgabe richtig sehe. Demzufolge solltest du den anderen Konstruktor von Bauteil bemühen.

    Kondensator::Kondensator(double nWert, string nName)
                    :Bauteil(nWert, nEinheit, nName)
    { // und dann? Was muss ich an dieser Stelle beachten?
    

    Was ist nEinheit? (Hint: Wie soll die Einheit von Kondensatoren heißen?)

    Du solltest dich wirklich nochmal intensiv mit der Thematik beschäftigen. Was du hier machst sieht arg nach rumprobieren aus, bei der Klausur hast du aber nur einen Versuch, die Aufgabe richtig zu lösen.



  • Da ich das Thema nun zum gefühlten 10x gelesen habe, denk ich etwas mehr verstanden zu haben.

    Da laut Aufgabenstellung F als Einheit deklariert werden soll und keine weiteren Attribute gerbaucht werden, wird diese im Standardkontr. geändert.

    nun erstmal zur Klasse:

    class Kondensator : public Bauteil
    {
      public:
       Kondensator();
       Kondensator(double nWert, string nName);
       void Parallel(Kondensator P1);
       static Kondensator Seriell(Kondensator P1,Kondensator P2,string nName); 
    
      //private: wird nicht benötigt da keine neuen Attribute gebraucht
      //bitte korriegen falls ich hier ein Denkfehler habe
    };
    

    Nun wieder zur Implementierung:

    da ich den Standardkontr. implementieren soll und die Einheit bei der Kindsklasse als "F" definiert wird, muss der Wert anders implementiert werden.
    Hab ich das so richtig verstanden?

    Kondensator::Kondensator() //standardkontr.
                :Bauteil(nWert, nEinheit, nName) //Konstruktoraufruf
    {
            //nun hat der Standardkonstr. keine Parameter
            //kann ich dann trotzdem nEinheit='F' definieren?
            //weil auf "Einheit" hab ich ja keinen Zugriff wegen Elternklasse
      nEinheit='F'
           //wenn falsch, bitte erläutern
    }
    

    selbe Spiel nun beim überladenen Konstr.

    Kondensator::Kondensator(double nWert, string nName)
                :Bauteil (nWert, nEinheit, nName)
    {
        //hier stellt sich die selbe Frage wie oben
        //die Parameter dürfen meines Wissens die selben Namen haben
        //aber macht es Sinn die Implementierung wie folgt zu machen?
    
       nWert=nWert; //?  Ein paar Tips dazu oder evtl etwas zum Nachschlagen online wäre echt hilfreich
       nName=nName;
       nEinheit='F'; //Obwohl der über.Konstr. kein derartigen Paramter hat?
    
    }
    

    Vielen Dank für die Mühe.



  • AntonC++ schrieb:

    Kondensator::Kondensator(double nWert, string nName)
                :Bauteil (nWert, nEinheit, nName)
    {
        //hier stellt sich die selbe Frage wie oben
        //die Parameter dürfen meines Wissens die selben Namen haben
        //aber macht es Sinn die Implementierung wie folgt zu machen?
    
       nWert=nWert; //?  Ein paar Tips dazu oder evtl etwas zum Nachschlagen online wäre echt hilfreich
       nName=nName;
       nEinheit='F'; //Obwohl der über.Konstr. kein derartigen Paramter hat?
                  
    }
    

    Die Zuweisungen im Konstruktor brauchst du nicht, da du die Parameter direkt an den Basisklassenkonstruktor weiterreichst. Und da jeder Konstruktor die Einheit 'F' hat, musst du diese auch direkt an den Basisklassenkonstruktor weitergeben.
    Also:

    Kondensator::Kondensator(double nWert, string nName)
                :Bauteil (nWert, 'F', nName)
    { 
    }
    

    Analog, der Defaultkonstruktor. Hier musst du Dir allerdings Defaultwerte für nName und nWert überlegen.



  • Indem ich nun den Parameter im Basiskonstruktor änder, wird nun

    nEinheit = 'F'
    

    ? oder eher

    Einheit='F'
    

    weil

    nEinheit=Einheit
    

    eigentlich

    sprich: da ich

    (double nWert, string nName)
    

    im Kondensator Konstruktor habe werden diese automatisch deklariert?

    Und weil nEinheit fehlt muss/kann ich diese im Basiskontruktor verändern?

    Fragen über Fragen 🙂

    Kann mich nicht oft genug bedanken.



  • Hmmm.... Ich versteh jetzt nicht was du genau wissen willst.
    An der Bauteil-Klasse musst du garnichts ändern. Ich glaube du solltest dir Klassen und Vererbung nochmal genauer anschauen. Im netz gibts genügend Beispiele und Tutorials.



  • AntonC++ schrieb:

    Da ich das Thema nun zum gefühlten 10x gelesen habe, denk ich etwas mehr verstanden zu haben.

    zigmal lesen bringt nichts, wenn du es nur überfliegst. Das scheint aber der Fall zu sein.

    Mal ein paar Fragen, um zu sehen wie weit du das verstanden hast:
    - ist das Attribut "Einheit" Bestandteil der Klasse "Kondensator", direkt oder indirekt?
    - welche Möglichkeiten gibt es, das Attribut "Einheit" eines Baustein-Objektes zu belegen? Wenn ja, welche?
    - Welche Möglichkeiten gibt es innerhalb eines Kondensator-Objektes, auf die Attribute des Baustein-Elternobjektes zuzugreifen?
    - Welche Möglichkeiten gibt es, von außerhalb auf das Baustein-Elternobjekt (und seine Attribute) eines Kondensator-Objektes zuzugreifen?



  • - ist das Attribut "Einheit" Bestandteil der Klasse "Kondensator", direkt oder indirekt?

    Einheit wurde in der Basisklasse unter protected deklariert, deswegen kann Klasse Kondensator direkt darauf zugreifen.

    - welche Möglichkeiten gibt es, das Attribut "Einheit" eines Baustein-Objektes zu belegen? Wenn ja, welche?

    Meinst du mit dem Baustein-Objekt eine Instanz?

    Wenn ich das Objekt erzeuge: "Bauteil T1(10,'F',K1)" habe ich "Einheit" ja nun 'F' zugewiesen.

    - Welche Möglichkeiten gibt es innerhalb eines Kondensator-Objektes, auf die Attribute des Baustein-Elternobjektes zuzugreifen?

    Ein Kondensator Objekt wäre ja "Kondensator K1(10,K1)" Der Inhalt der Klammer wird den Attributen zugewiesen.

    - Welche Möglichkeiten gibt es, von außerhalb auf das Baustein-Elternobjekt (und seine Attribute) eines Kondensator-Objektes zuzugreifen?

    Heißt Außerhalb, wenn man nicht in der Klasse ist?
    Muss bei der Frage leider passen.
    Kümmer mich aber sofort drum.

    Ich hoffe ich bin nicht zu weit von der Wahrheit entfernt...



  • AntonC++ schrieb:

    - ist das Attribut "Einheit" Bestandteil der Klasse "Kondensator", direkt oder indirekt?

    Einheit wurde in der Basisklasse unter protected deklariert, deswegen kann Klasse Kondensator direkt darauf zugreifen.

    Es geht nicht um den zugriff, sondern darum, ob es ein bestandteil der Klasse ist, d.h. ob ein Kondensator-Objekt (also eine Instanz der Klasse "Kondensator") ein Attribut "Einheit" hat.

    - welche Möglichkeiten gibt es, das Attribut "Einheit" eines Baustein-Objektes zu belegen? Wenn ja, welche?

    Meinst du mit dem Baustein-Objekt eine Instanz?

    Objekte sind (im Objektorientierten Sinn) Instanzen einer Klasse, ja.

    Wenn ich das Objekt erzeuge: "Bauteil T1(10,'F',K1)" habe ich "Einheit" ja nun 'F' zugewiesen.

    Hast du. Und welche Möglichkeiten hast du noch, um darauf zuzugreifen, außer über den Konstruktor?

    - Welche Möglichkeiten gibt es innerhalb eines Kondensator-Objektes, auf die Attribute des Baustein-Elternobjektes zuzugreifen?

    Ein Kondensator Objekt wäre ja "Kondensator K1(10,K1)" Der Inhalt der Klammer wird den Attributen zugewiesen.

    Es ging in der Frage darum, wie du innerhalb des Kondensator-Objektes, also innerhalb der Methoden von Kondensator auf die Attribute der Elternklasse zugreifen kannst. Das hast du nicht beantwortet.

    - Welche Möglichkeiten gibt es, von außerhalb auf das Baustein-Elternobjekt (und seine Attribute) eines Kondensator-Objektes zuzugreifen?

    Heißt Außerhalb, wenn man nicht in der Klasse ist?
    Muss bei der Frage leider passen.
    Kümmer mich aber sofort drum.

    Dann mal los 🙂



  • Wenn ein Kondensator Objekt erstelle soll es ja das Attribut "Einheit" besitzen. Dementsprechend hat es dieses, wie entscheide ich ob dieses direkt oder indirekt ist?

    - Welche Möglichkeiten gibt es innerhalb eines Kondensator-Objektes, auf die Attribute des Baustein-Elternobjektes zuzugreifen?

    außer mit dem Konstruktor kann ich auch mit methoden auf die Attribute zugreifen

    Es ging in der Frage darum, wie du innerhalb des Kondensator-Objektes, also innerhalb der Methoden von Kondensator auf die Attribute der Elternklasse zugreifen kannst. Das hast du nicht beantwortet.

    Greife ich nicht auf die Attribute zu indem ich das Objekt erstelle und innerhalb der Klammern "Werte" angebe? Bei dieser Frage steh ich grad sehr auf dem Schlauch.

    - Welche Möglichkeiten gibt es, von außerhalb auf das Baustein-Elternobjekt (und seine Attribute) eines Kondensator-Objektes zuzugreifen?

    Muss zugeben das ich gerade keinen Durchblick hab...

    Nun vielleicht eine Grundlegen Frage:

    Ich habe die Bauteil-Klasse, diese übergibt mir ihre Daten auf meine Kondensator-Klasse.
    Zugriff habe ich auf protected und public, und privat nur eingeschränkt.

    wenn ich nun meine Kondensator-Klasse erstelle, welche Attribute hat diese durch

    class Kondensator : public Bauteil
    

    mir is nocht nicht richtig klar, wie die Attribute sich "verteilen"



  • Vielleicht ist es einfacher, wenn man ein anderes Beispiel bringt.

    Wir haben die Klasse figure und wollen triangle ableiten.

    class figure 
    {
      private:
        string name;
        color paint;
        bool visible;
      public:
        figure(string n, color c, bool v);
        virtual ~figure();
        color get_color();
        bool get_visible();
        string get_name();
        string get_colorname();
        virtual float calc_surface() = 0; // Abstrakte Klasse durch rein
        virtual void display() = 0; // virtuelle Methoden.
    };
    
    class triangle : public figure
    {
      private:
        double (a,b,c,s);
      public:
        triangle();
        triangle(string n, color c, bool v, double x, double y, double z);
        ~triangle();
        static bool is_triangle(double a, double b, double c);
        void display();
    };
    

    wenn ich nun den überl. Konstruktor von triangle implementier:

    triangle::triangle(string n, color c, bool v, double x, double y, double z)
             :figure(n,c,v) //es werden n,c,v übernommen (von figure)
    {
       a=x;
       b=y;
       c=z;
            //"triangle" beinhaltet diesmal alle parameter des basiskonstruktors, wieso is das bei der anderen Aufgabe nicht der Fall? 
    }
    


  • AntonC++ schrieb:

    Wenn ein Kondensator Objekt erstelle soll es ja das Attribut "Einheit" besitzen. Dementsprechend hat es dieses, wie entscheide ich ob dieses direkt oder indirekt ist?

    Mit direkt/indirekt meine ich, ob es das Attribut des ondensators ist, oder ob es ein Attribut einer Elternklasse ist. Das Attribut Einheit ist ein Attribut von Bauteil, und da Kondensator von Bauteil erbt, ist Bauteil ein Teil von Kondensator. Damit hat Kondensator indirekt über Bauteil auch ein Einheit-Attribut. Das ist eine grunlegende Eigenschaft der Vererbung: Vererbung bedeutet "ist-ein"-Beziehung, d.h. ein Kondensator ist ein Bauteil - und hat daher logischerweise alle Eigenschaften (Attribute) eines Bauteils.

    - Welche Möglichkeiten gibt es innerhalb eines Kondensator-Objektes, auf die Attribute des Baustein-Elternobjektes zuzugreifen?

    außer mit dem Konstruktor kann ich auch mit methoden auf die Attribute zugreifen

    Du kannst mit dem Konstruktor nicht von außen auf das Objekt zugreifen. Das Objekt wird durch den Konstruktor erst erzeugt. Du kannst über die Parameter des Konstruktors aber beeinflussen, wie er die Attribute initialisiert.

    Greife ich nicht auf die Attribute zu indem ich das Objekt erstelle und innerhalb der Klammern "Werte" angebe? Bei dieser Frage steh ich grad sehr auf dem Schlauch.

    Mit "in den Klammern Werte angeben" meinst du vermutlich die Initialisierungsliste - damit initislisierst du die Attribute, d.h. legst fest wie sie erzeugt werde. Zugreifen kannst du auf die Attribute von außen über die öffentlichen Methoden, und im Kondensator kannst du auf die protected Attribute des Bauteil-Objektes zugreifen, das im jeweiligen Kondensator-Objekt "eingebettet" ist.

    - Welche Möglichkeiten gibt es, von außerhalb auf das Baustein-Elternobjekt (und seine Attribute) eines Kondensator-Objektes zuzugreifen?

    Muss zugeben das ich gerade keinen Durchblick hab...

    Wie oben beschrieben ist ein Kondensator auch ein Bauteil, das bedeutet in C++, dass jedes Kondenator-Objekt ein bauteil-Unterobjekt besitzt. Das sollte im Buch deiner Wahl aber auch erklärt sein.

    Nun vielleicht eine Grundlegen Frage:

    Ich habe die Bauteil-Klasse, diese übergibt mir ihre Daten auf meine Kondensator-Klasse.

    Nein, nicht so wirklich. Siehe oben...

    Zugriff habe ich auf protected und public, und privat nur eingeschränkt.

    Nein. Auf privat hast du überhat keinen Zugriff.

    Hoffe, das macht es etwas klarer 🙂


Anmelden zum Antworten