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
1
/******** Vererbung 1 : Einfache Vererbung von zwei Klassen *******/
2
3
4
#include<iostream>
5
6
usingnamespacestd;
7
8
/*********** Elternklasse ************/
9
10
classEltern
11
{
12
private:
13
14
public:
15
charF_or_M;// Männlich oder weiblich? Eines der beiden ist wohl auch der Sohn.
16
intAnzahlKinder;//...der Sohn darf noch keine Kinder haben
17
18
19
protected:
20
boolerziehen;//...denn das können nur die Eltern
21
22
};
23
24
/*********** Kindklasse *************/
25
26
classSohn:publicEltern
27
{//...alle Attribute, die bei "Eltern" nicht in protected stehen werden hierher vererbt
28
public:
29
intNote_in_Programmieren;// Schulnoten kriegt nur der Sohn.
30
boolheimliche_freundin;// Heimliche Freundin hat auch nur der Sohn.
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.
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.
@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?
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.
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.
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.
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.
@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:
1
classMensch// Basisklasse für Kind und Eltern
2
{
3
protected:
4
5
std::stringname;
6
7
};
8
9
classEltern:publicMensch
10
{
11
std::list<Kind&>kinder;// Container für 0 bis N Kinder
12
};
13
14
classKind:publicMensch
15
{
16
Eltern&vater;// genau ein Vater
17
Eltern&mutter;// genau eine Mutter
18
};
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.
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
1
classMensch
2
{
3
private:
4
5
std::stringname;
6
7
Mensch*vater;
8
Mensch*mutter;
9
std::list<Mensch*>kinder;
10
};
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.