Konstruktor-Initialisierung
-
Guten Mittag,
ich habe ein Problem. Und zwar: Von eine Klasse Base leite ich mehrere Klassen DerivedA, DerivedB etc. ab. Nun will ich deren Membervariablen und die Private-Membervariablen von Base in der Konstruktor-Initialisierung von Derived initialisieren. Der MSVC meldet mir aber z.B.:L:\Test\Object.cpp(139) : error C2614: 'DerivedA' : illegal member initialization: 'm_type' is not a base or member
Wie kann ich das bewerkstellingen? Ich möchte die Initialisierungsliste benutzen und nicht den vorinitialisierten Variablen einen Wert zuweisen. Bitte helft mir!
-
private = > protected könnte dir helfen wenn ich das richtig verstanden habe
-
Original erstellt von <Huppi>:
Von eine Klasse Base leite ich mehrere Klassen DerivedA, DerivedB etc. ab. Nun will ich deren Membervariablen und die Private-Membervariablen von Base in der Konstruktor-Initialisierung von Derived initialisieren.ein Ctor soll die eigene Klasse initialisieren und nicht die base Klasse. Um die base Klasse zu initialisieren rufe den Ctor der base klasse auf (in der initialisierungs liste)
-
Hi
Es wäre gut wenn du mal deine Klassen kurz zusammen gefasst postest. Musst ja nicht alle member mit schreiben.
Hast du die member der Basisklasse auf die du zu greifen willst als protected oder private deklariert ?
Wenn sie private sind, musst du sie wohl vom Konstruktor der Basisklasse intitialisieren lassen und in der abgeleiteten klasse den Basisklassenkonstruktor mit aufrufen.
Ich hoffe ich hab das jetz richtig verstanden.
bsp:
class Base { private: int a; int b; protected: int c; int d; public: Base(int pa,int pb):a(pa),b(pb){} }; class Derived : public Base { public: Derived(int pa,int pb,int pc,int pd):Base(pa,pb),c(pc),d(pd){} };
meintest du sowas ?
-
Ja, genau... Danke euch allen. Schnelle Hilfe!
-
@prolog: Ich weiß, es ist nur ein Beispiel, aber trotzdem: Das ist ganz mieser Stil! Variablen sollten immer private sein. Außerdem bleiben c und d uninitialisiert, falls man ein Base für sich erzeugt.
@Huppi: Halte dich an Shades Vorschlag und schreibe einen passenden Konstruktor (evtl. protected), den Derived verwenden kann.
Stefan.
-
Original erstellt von <StefanD>:
@prolog: Ich weiß, es ist nur ein Beispiel, aber trotzdem: Das ist ganz mieser Stil! Variablen sollten immer private sein. Außerdem bleiben c und d uninitialisiert, falls man ein Base für sich erzeugt.
Stefan.Bei letzterem gebe ich dir recht.
ABER: Variablen sollten immer privat sein?
Und sag jetz nicht wegen der Datenkapselung.
Wozu gibt es wohl das protected keyword ?
[ Dieser Beitrag wurde am 26.06.2003 um 19:20 Uhr von prolog editiert. ]
-
@prolog:
/ironie an:
Mensch du bist so ein Depperle! Du machst einfach eine SetVar(wert) methode und setzt die als Protected:
beispiel:class foo { public: foo(); ~foo(); protected: void SetI(int x); private: int x,y,z; };
Du bist ja soooo dumm
/ironie aus..
Also das man member IMMER private deklarieren soll ist mir auch neu!
Man soll die member als private deklarieren die für weitere Klassen nicht gebraucht werden.
Aber im Falle des berühmten animals Beispiel:class CAnimal { public: CAnimal(); ~CAnimal(); void SetAge(int x); protected: int Age; }; class CDog:public cAnimal { public: ... } int main() { CDog Hello; Hello.SetAge(10); //geht nicht da Age private und damit in Dog nicht enthalten.. }
Von daher halte ich von der Idee nichts. Dinge die geerbte Klassen nichts angehen als Private. Dinge, die die Klassen gemeinsam haben als protected!!!
-
fuer normale klassen sollten die member immer private sein (ja, auch protected ist nicht gut)
denn es geht schliesslich niemanden an welche member wir haben...
und setVar() ist auch bloedsinn - man sollte keine variablen damit zuweisen, sondern attribute setzen.
zB macht es bei einem motor keinen sinn im nachhinein noch die anzahl der zylinder zu aendern - obwohl die klasse motor also eine variable fuer die anzahl der zylinder hat (dabei ist es egal ob diese variable ein float, double, short, char oder std::list ist) gibt es trotzdem kein setZylinder()
mit getVar() verhaelt es sich aehnlich. manche variablen muessen kein get haben
@stealth:
warum protected? mir ist das zu offen (da kann ja jeder rumpfuschen)
in deinem fall ist es sowieso bloedsinn, da setAge() ja nicht methode von Dog ist, sondern von Animal.es geht Dog nichts an wie Animal die Sachen speichert - Dog sollte, obwohl es ein Animal ist, trotzdem nicht an der implementierung von Animal haengen. Wenn wir aus setAlter(int) ein setAlter(float) machen, dann sollte Dog das hinnehmen - einfach neukompilieren, aber ein aendern von Dog ist nicht noetig.
-
Hi
Ich hab wirklich nichts gegen Datenkapselung.
Aber in manchen situationen ist es nötig(einfacher)direkten Zugriff auf die Variablen zu bekommen.Von dem Gesichtspunkt aus dürfte man auch keine freunde deklarieren.
Ich versuche auch wo es geht die Datenkapselung nicht aufzuweichen, aber ich mach mir auch nicht mehr Arbeit als nötig.Und wie gesagt es war nur ein Beispiel. Also nichts für ungut.
-
@prolog: Es ist mit C++ *nie* nötig, direkten Zugriff auf eine Variable einer fremden Klasse zu haben! Sag mir nur ein einziges Beispiel, wo es wirklich nötig ist. Hingegen sind die Beispiele, wo ein direkter Zugriff sich als fatal erwiesen hat Legion. Einige Leute (z.B. Herr Fowler, wenn ich mich nicht irre) plädieren sogar mit ziemlich guten Gründen dafür, selbst in der Klasse, der die Variablen gehören, ausschließlich per Methode darauf zuzugreifen. Warum wohl?
Dein zweites Statement scheint mir ehrlicher: "ich mach mir auch nicht mehr Arbeit als nötig" (wobei da auch schon wieder ein "nötig" auftaucht *g*). Und Leute, die sich möglichst wenig Arbeit machen wollen, kosten am Ende meistens Zeit, Geld und Nerven.
Ich plädiere nicht dafür, in diesem Punkt niemals Ausnahmen zu machen, denn manchmal ist eben der Arbeitsaufwand doch ein Punkt. Oder eine Schnittstelle, die von Gettern und Settern nur so strotzt, und weiter nichts aufzuweisen hat. Aber zu solchen Ausnahmen sollte wirklich ein guter Grund gehören. Der noch einmal und noch einmal überdacht wird. Geht es nicht mit etwas Refactoring doch anders? Haben wir eine also Design-Schwäche, so daß es nötig erscheint? Undsoweiter.....
Man kann kaum etwas falsch machen, wenn grundsätzlich alle Variablen private sind - und eine Menge, wenn es an der falschen Stelle zu viel Arbeit war.
Stefan.
-
Original erstellt von <StefanD>:
**@prolog: Es ist mit C++ *nie* nötig, direkten Zugriff auf eine Variable einer fremden Klasse zu haben! Sag mir nur ein einziges Beispiel, wo es wirklich nötig ist. Hingegen sind die Beispiele, wo ein direkter Zugriff sich als fatal erwiesen hat Legion. Einige Leute (z.B. Herr Fowler, wenn ich mich nicht irre) plädieren sogar mit ziemlich guten Gründen dafür, selbst in der Klasse, der die Variablen gehören, ausschließlich per Methode darauf zuzugreifen. Warum wohl?Dein zweites Statement scheint mir ehrlicher: "ich mach mir auch nicht mehr Arbeit als nötig" (wobei da auch schon wieder ein "nötig" auftaucht *g*). Und Leute, die sich möglichst wenig Arbeit machen wollen, kosten am Ende meistens Zeit, Geld und Nerven.
Ich plädiere nicht dafür, in diesem Punkt niemals Ausnahmen zu machen, denn manchmal ist eben der Arbeitsaufwand doch ein Punkt. Oder eine Schnittstelle, die von Gettern und Settern nur so strotzt, und weiter nichts aufzuweisen hat. Aber zu solchen Ausnahmen sollte wirklich ein guter Grund gehören. Der noch einmal und noch einmal überdacht wird. Geht es nicht mit etwas Refactoring doch anders? Haben wir eine also Design-Schwäche, so daß es nötig erscheint? Undsoweiter.....
Man kann kaum etwas falsch machen, wenn grundsätzlich alle Variablen private sind - und eine Menge, wenn es an der falschen Stelle zu viel Arbeit war.
Stefan.**
Ich hab in meinem Kleinen Stretegiespiel zur Zeit 20-30 Klassen. Die alle mit Settern und Gettern auszustatten würde
a) unmenge an Zeit annehmen.
b) ich kapsel lieber die Klassen in eine MainKlasse und lasse nur die Mainklasse auf verschiedene Elemente zugreifen (machen elemente kann noch nicht mal die MainKlasse direkt benutzen!!!)
Aber ALLE vars in Klassen mit Settern und Gettern auszustatten ist meiner Meinung nach unsinn...Hatte noch nie einen unbefugten zugriff auf einer meiner Klassen. Da ist es dann halt auch wieder ne Frage in wieweit man zugriffe gestaltet. Aber ich hab viel mehr Bug-Probleme mit Non-Null-pointern als mit unauthorisierten member-aufrufen...
-
du hast eine klasse weltraumschiff, die eine eigenschaft "geschwindigkeit (int)" besitzt. du kannst beschleunigen und abbremsen (geschw. erhöhen und vermindern)
-
du deklarierst geschwindigkeit im public bereich.
jedesmal, wenn du die geschw. erhöhen willst, schreibst du instanz.geschw + 2;
jetzt merkst du aber, es ist dir zu langsam. du willst lieber + 4. schreibst du jetzt überall + 4 statt + 2? ist das keine tipparbeit? -
du machst sie private und definierst beschleunigen() und abbremsen() (vereinfacht):
void weltraumschiff::beschleunigen () { geschwindigkeit += 4; } void weltraumschiff::abbremsen () { geschwindigkeit -= 4; }
jetzt musst du nur die funktionen ändern, wenn du das verhalten der klasse im ganzen projekt ändern willst.
deshalb kann es auch sinn machen, innerhalb einer klasse immer die passenden "Getter" und "Setter" einzusetzen, wenn es auch nicht immer direkt "Getter" und "Setter" sind.
was ich sagen will: bei einem bug hast du den fehler einfach leichter einzugrenzen
-
-
Ich hab in meinem Kleinen Stretegiespiel zur Zeit 20-30 Klassen. Die alle mit Settern und Gettern auszustatten würde
a) unmenge an Zeit annehmen.
b) ich kapsel lieber die Klassen in eine MainKlasse und lasse nur die Mainklasse auf verschiedene Elemente zugreifen (machen elemente kann noch nicht mal die MainKlasse direkt benutzen!!!)
Aber ALLE vars in Klassen mit Settern und Gettern auszustatten ist meiner Meinung nach unsinn...Und ich schreibe privat ein GUI-Framework für Windows mit mehr als 250 Klassen, wo auf *alle* Variablen mit Gettern und Settern zugegriffen wird.
Beruflich sind es bestimmt fünfmal soviele (schwer zu schätzen). Das alte Zeugs ist gut sieben Jahre alt, da hat man sich schonmal die eine oder andere Schlampigkeit geleistet. Und dann kam Y2K, und dann kam der Euro.... Und die Jungs, die diesen Mist verbrochen hatten, waren längst woanders. Ich kann dir nur sagen: Wir hatten richtig Spaß!
Mir ist das nicht zuviel Arbeit. Ich habe einfach am eigenen Leib erlebt, wozu Kapselung gut ist.
Stefan.
-
Original erstellt von davie:
**du hast eine klasse weltraumschiff, die eine eigenschaft "geschwindigkeit (int)" besitzt. du kannst beschleunigen und abbremsen (geschw. erhöhen und vermindern)-
du deklarierst geschwindigkeit im public bereich.
jedesmal, wenn du die geschw. erhöhen willst, schreibst du instanz.geschw + 2;
jetzt merkst du aber, es ist dir zu langsam. du willst lieber + 4. schreibst du jetzt überall + 4 statt + 2? ist das keine tipparbeit? -
du machst sie private und definierst beschleunigen() und abbremsen() (vereinfacht):
void weltraumschiff::beschleunigen () { geschwindigkeit += 4; } void weltraumschiff::abbremsen () { geschwindigkeit -= 4; }
jetzt musst du nur die funktionen ändern, wenn du das verhalten der klasse im ganzen projekt ändern willst.
deshalb kann es auch sinn machen, innerhalb einer klasse immer die passenden "Getter" und "Setter" einzusetzen, wenn es auch nicht immer direkt "Getter" und "Setter" sind.
was ich sagen will: bei einem bug hast du den fehler einfach leichter einzugrenzen**
Bei solchen sachen ist es ja klar.
Aber nehmen wir mal an du hast die BaseClass ship mit den member speed und den settern und gettern. Wenn du speed als protected deklarierst kannst du diese member automatisch an die nächsten Raumschiffe weitergeben (Freighter, Warship etc..)
Wenn du speed als private deklarierst werden sie aber NICHT an die abgeleiteten Klassen weitergegeben!
Und ich benutze schon Setter und Gettern. Aber bei manchen Speicher-Klassen, hab ich lieber direkten zugriff auf die Member da, diese Klassen sowieso NUR von einer MainKlasse aus gesteuert werden.
Zum beispiel die Klasse sSprite bei mirclass sSprite { public: sSprite() { next=prev=NULL; } ~sSprite() { next=prev=NULL; delete Image; } ... };
die sSprite klasse wird nur von der Klasse cGrafik benutzt die Sprites, laden und anzeigen kann. Andere Klassen haben keinen Zugriff auf cGrafik sondern nur auf die Funktionen ShowSprite(char *Name); und LoadSprite(char *Name);
Deshalb halte ich zu internsives OOP für zu übertrieben!
-
-
Original erstellt von <StefanD>:
**Und ich schreibe privat ein GUI-Framework für Windows mit mehr als 250 Klassen, wo auf *alle* Variablen mit Gettern und Settern zugegriffen wird.Beruflich sind es bestimmt fünfmal soviele (schwer zu schätzen). Das alte Zeugs ist gut sieben Jahre alt, da hat man sich schonmal die eine oder andere Schlampigkeit geleistet. Und dann kam Y2K, und dann kam der Euro.... Und die Jungs, die diesen Mist verbrochen hatten, waren längst woanders. Ich kann dir nur sagen: Wir hatten richtig Spaß!
Mir ist das nicht zuviel Arbeit. Ich habe einfach am eigenen Leib erlebt, wozu Kapselung gut ist.
Stefan.**
Hab einen Post weiter oben ein Beispiel gepostet.
Klar ist Kapselung wichtig. Aber wenn die Klasse nur von EINER Kontrollklasse verwendet wird, ist es doch relativ wurscht ob man direkt auf die Vars zugreift oder setter und getter einbaut.Für Klassen auf die mehrere Objekte zugreifen (sagen wir mal eine Globale Klasse) wird natürlich nicht für alle zugänglich gemacht!
Sonst würde ja in meinem Beispiel dauernd jemand (wenn ich Pech hab) die Zeiger auf NULL setzten oder sonst wie verlinken!
-
du benutzt die struktur also nur zum datenspeichern. pass aber auf, dass du dir selbst nicht reinpfuschst. auch nach 2 jahren pause nicht.
zu deinem beispiel:
wenn ich speed private mache, können die abgeleiteten klassen speed nicht verändern, aber über die getter und setter methoden schon. wo ist das problem?
eine fremde klasse könnte hier dann ohne spezielle getter/setter sehr gut herumpfuschen.
-
Original erstellt von davie:
**du benutzt die struktur also nur zum datenspeichern. pass aber auf, dass du dir selbst nicht reinpfuschst. auch nach 2 jahren pause nicht.zu deinem beispiel:
wenn ich speed private mache, können die abgeleiteten klassen speed nicht verändern, aber über die getter und setter methoden schon. wo ist das problem?
eine fremde klasse könnte hier dann ohne spezielle getter/setter sehr gut herumpfuschen.**Ok, dann werden also Base Private member an "kinder" weiter abgeleitet aber sie können nicht darauf zugreifen!
Praktisch so einer art versteckte Variable!
Aber was ist wenn ein Freighter mit Faktor 2 fliegt und das Warship mit Faktor 4?? Was wäre dann dein Vorschlag?
-
Hi
Huhu. Es war nur ein Beispiel. Ich machs jetz mal wie die Grashalme im Wind und beuge mich. Ok. Datenkapselung über alles. Ich werde mich bessern versprochen.
-
void beschleunige (double faktor) { speed*=faktor; }
zum beispiel. kommt halt drauf an, was du willst. willst du das verhalten von beschleunigen/abbremsen den kind-klassen überlassen, wäre polymorphie vielleicht auch passend.