mikrocontroller.net

Forum: PC-Programmierung C++ - Problem mit protected


Autor: Johannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute!

Ich habe eine Frage zu C++ zur Vererbung von Klassen.
Hier ein Beispielcode, den ich gerade programmiert habe. Leider tritt 
bei mir in VC++ der Fehler "C2248" auf

"Kein Zugriff auf protected Member, dessen Deklaration in der 
Eltern-Klasse erfolgte."


Ich möchte, dass ich von der Klasse "Sohn" NICHT auf das Attribut 
"erziehen" zugreifen kann, da ein "Sohn" nicht erziehen darf.


Hier der Code
/********    Vererbung 1 : Einfache Vererbung von zwei Klassen *******/


#include <iostream>

using namespace std;

/*********** Elternklasse ************/

class Eltern
{
private:
    
public:
  char F_or_M;                        // Männlich oder weiblich? Eines der beiden ist wohl auch der Sohn.                                          
  int AnzahlKinder;                      //...der Sohn darf noch keine Kinder haben
                                

protected:
  bool erziehen;                        //...denn das können nur die Eltern

};

/*********** Kindklasse *************/

class Sohn : public Eltern
{                                //...alle Attribute, die bei "Eltern" nicht in protected stehen werden hierher vererbt
public:
  int Note_in_Programmieren;                  // Schulnoten kriegt nur der Sohn.
  bool heimliche_freundin;                  // Heimliche Freundin hat auch nur der Sohn.
};



/****************************** MAIN-Funktion   ****************************/



int main (void)
{
  Eltern Mutti;
  Mutti.F_or_M = 'f';                    // Mutti ist weiblich
  Mutti.erziehen = true;                  // sie erzieht auch noch.

  Sohn Johannes;                      // Objekt "Johannes" anlegen
  Johannes.Note_in_Programmieren = 675;            
  Johannes.heimliche_freundin = true;          
  


  cout << Johannes.Note_in_Programmieren << endl;

  system("pause");
  return 0;
}



Wo liegt mein Fehler?


Vielen Dank schon mal!

Gruß
Joh.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
kann es sein das es irgenwie verkehrt rum ist? Warum fängst du nicht bei 
einer person an und leidest davon den Sohn und dann die Eltern ab. Warum 
ist der Sohn von den Eltern abgeleiter, das macht doch überhaupt kein 
sinn.

Das Protekt wirkt sich innerhalb der Objekte aus. Die greifst sogar von 
ausen auf dem member zu, dafür sollte man Set und Get Methoden 
schreiben. Wenn ein member protected sagt aus das das Member nur in 
einer abgeleitet klasse verwendet werden darf aber nicht von aussen.

Autor: Yalu X. (yalu) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du versuchst, von main aus auf das protected Element erziehen von
Mutti zuzugreifen. Das geht nicht. Du könntest aber von main aus
eine public-Methode von Mutti aufrufen, die erziehen auf true setzt.

Autor: Johannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Peter:

Es soll ja genau diesen Zusammenhang verdeutlichen. Dass sich der Sohn 
von den Eltern "ableitet", sprich, Eigenschaften der Eltern erbt, jedoch 
nicht alle.

Dass man normalerweise set- und get-Funktionen schreibt, um auf die 
Attribute (aus Sicherheitsgründen) nicht direkt zugreifen zu können, ist 
mir klar. Dennoch möchte ich ohne set-/getFunktionen die Attribute von 
Eltern- und Sohn folgendermaßen setzen, wie es in den Kommentaren steht.

Warum funktioniert das nun nicht?

Autor: Johannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Yalu X.:

Deine Aussage wäre für mich plauibel, wenn "bool erziehen" in private 
von "Eltern" und NICHT in public von "Eltern" stünde.

Autor: Yalu X. (yalu) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Johannes schrieb:
> Deine Aussage wäre für mich plauibel, wenn "bool erziehen" in private
> von "Eltern" und NICHT in public von "Eltern" stünde.

erziehen steht eben nicht in public von Eltern sondern in
protected. Und protected ist außerhalb der Klasse genauso wenig sichtbar
wie private.

Autor: Johannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok.

Und wie kann ich dann "bool erziehen" nur vom Objekt der Klasse "Eltern" 
sichtbar machen?

Autor: DerAlbi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Funktionalität die du suchst gibt es nicht.
Entweder
a) privat, dann darf NUR die klasse und deren Methoden drauf zugreifen,
b) pulic, dann darf jeder
c) protected dann darf auch eine abgeleitete klasse darauf zugreifen, 
ansonsten verhält sich das wie private.

Du suchst: "machs für alle sichbar außer für abgeleitete klassen" Das 
ist unfug bzw ein konzeptfehler. Das bekommst du nur mit einer anderen 
ableitungshierarchie hin.

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Johannes schrieb:
> Es soll ja genau diesen Zusammenhang verdeutlichen. Dass sich der Sohn
> von den Eltern "ableitet", sprich, Eigenschaften der Eltern erbt, jedoch
> nicht alle.

Das ist nicht das, was die Vererbungsrelation in C++ ausdrückt.

Daher wirst du mit dem Ansatz, "Sohn" von "Eltern" abzuleiten, immer und 
an allen Stellen immense Schmerzen haben.

Autor: U.R. Schmitt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Johannes,

hör auf das was Martin schreibt.
Vererbung bei OO Programmierung hat nur bedingt mit biologischer Eltern 
Kind Beziehung zu tun, auch wenn der Begriff daher abgeleitet ist.
Es hat mehr damit zu tun daß du allgemeinere Eigenschaften in Eltern 
(übergeordneten) Klassen ablegst, und spezifische dann in den Kind 
Klassen.

Ein nettes Beispiel ist

Fahrzeug
2-Rad : Fahrzeug
4-Rad : Fahrzeug
Fahrrad : 2-Rad
Auto: 4-Rad
PKW : Auto
LKW : Auto

jedes Fahrzeug hat z.B. die Methode beschleunigen(), bremsen(), lenken() 
und parken(), oder aquch die Variable Eigentümer.
Die Implementierung ob man jetzt bei einem Fahrrad beide Handbremsen 
ziehen muss zum Bremsen oder im PKW das Bremspedal treten, ist in den 
Klassen ggf. völlig unterschiedlich implementiert (Überladen, bzw. 
abstrakt in der Elternklasse definiert).
Wenn man aber ein Fahrzeug zum Fahren benutzen will, kann man jetzt 
unabhängig was für ein Fahrzeug man hat, die Methoden zum beschleunigen, 
bremsen, lenken usw. benutzen, ohne die innere Implementierung genau 
kennen zu müssen.

Autor: besucher (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Johannes: Das Problem liegt hier:

class Sohn : public Eltern

Die Vererbung drückt eine "Ist-ein"-Relation aus, es wird also 
behauptet: "Ein Sohn ist ein Eltern-(teil)", und hat deshalb ALLE 
Eigenschaften von Eltern, plus einige besondere, die nur er selbst hat.

Da das in der Realität nicht so ist, ist der Modellansatz falsch und du 
hast die beschriebenen Probleme.

Folgender Ansatz könnte in dieser Hinsicht besser sein:
class Mensch // Basisklasse für Kind und Eltern
{
protected:

    std::string name;
    
};

class Eltern : public Mensch
{
    std::list<Kind &> kinder; // Container für 0 bis N Kinder
};

class Kind : public Mensch
{
    Eltern & vater;    // genau ein Vater
    Eltern & mutter;   // genau eine Mutter
};

Wobei auch das nicht der Weisheit letzter Schluss ist, denn was 
passiert, wenn aus Kindern Eltern werden? Und Kinder sind sie trotzdem 
noch. Vielleicht muss man das anders lösen als mit Ableitung.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
besucher schrieb:

> Wobei auch das nicht der Weisheit letzter Schluss ist, denn was
> passiert, wenn aus Kindern Eltern werden? Und Kinder sind sie trotzdem
> noch. Vielleicht muss man das anders lösen als mit Ableitung.

Muss man.
Ob jemand Eltern oder Kind ist, ist eine Frage des Objekts und nicht der 
Klasse. Hier wird versucht etwas in eine Klassenstruktur zu quetschen, 
was da so nicht hineingehört. Die Eltern-Kind Beziehung ergibt sich aus 
dem dynamischen Zusammenhang, welche Mensch bei einem anderen Menschen 
als Vater oder Mutter eingetragen ist, bzw. welche Personen bei einem 
anderen Menschen als Kind eingetragen ist.

Aber jeder Mensch hat erstmal einen Vater UND eine Mutter UND Kinder. 
Wobei natürlich es auch den Fall geben kann, dass man sie nicht kennt.

Also so
class Mensch
{
  private:

    std::string        name;

    Mensch*            vater;
    Mensch*            mutter;
    std::list<Mensch*> kinder;
};

damit kann man jetzt alle Verwandschaftsbeziehungen ausdrücken und 
entsprechende Relationen erzeugen bzw abfragen.
Überlegt euch einfach mal, wie in einer starren Hierarchie wie weiter 
oben die Beziehungen "Ist Opa von", "Ist Oma von", "ist Tante von", "Ist 
Neffe von" auszudrücken wären. Es geht nicht.

Bei Klassenhierarchien muss man aufpassen, dass man die Dinge nicht 
übertreibt und sich ein zu starres Korsett anlegt, dass in weiterer 
Folge unflexibel ist. Weniger ist da oft mehr.
Im konkreten Fall ist "Vater sein", "Mutter sein", "Kind sein" eine 
Eigenschaft einer Person, die sich aus dem zusammenhang ergibt. Aber 
niemand kommt zur Welt und 'IST EINE' Mutter.

Für Klassen sollte man sich immer die Frage stellen: Wenn eine Klasse 
eine 'IST-EIN' Beziehung ausdrückt, gilt das dann für meinen Fall? 'IST' 
Herbert wirklich ein Kind oder ist er nicht in erster Linie Mensch, der 
nur dadurch zum Kind wird, dass er Vater und Mutter hat und dort jeweils 
als Kind eingetragen ist. D.h. die Eigenschaft 'Kind sein' ergibt sich 
aus dem Zusammenhang von mehreren Objekten, aber eine Person ist nicht 
eines aus der Typisierung Kind/Vater/Mutter.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.