Warum wird der Konstruktor nicht vererbt?
-
hallo,
warum wird der konstruktor nicht, ebenso wie andere methoden auch, vererbt?class foo { public: foo(int a) : m_a(a) {} protected: int m_a; }; class bar : public foo {};bar bekommt nicht den konstruktor von foo. warum muss man extra explizit schreiben:
bar(int a) : foo(a) {}
-
Weil die abgeleitete Klasse nicht zwangsläufig auf die gleiche Art konstruiert werden soll wie die Basisklasse. D.h. du musst den entsprechenden Konstruktor einfach explizit aufrufen.
grüße
-
David_pb schrieb:
Weil die abgeleitete Klasse nicht zwangsläufig auf die gleiche Art konstruiert werden soll wie die Basisklasse.
Zwangsläufig wäre blöd, aber default-mäßig wäre doch nicht schlecht; es sei denn, man hätte dann keine Möglichkeit, den Basisklassen-Konstruktor zu verbieten. Wenn man die Schnittstelle für den Basisklassen-Konstruktor verstecken wollte, könnte man sie aber private machen. Ich verstehe das nicht, meistens ist es doch beim Ableiten eher so, dass man die Dinge, die man nicht neu aufführt, behalten will.
-
David_pb schrieb:
Weil die abgeleitete Klasse nicht zwangsläufig auf die gleiche Art konstruiert werden soll wie die Basisklasse. D.h. du musst den entsprechenden Konstruktor einfach explizit aufrufen.
grüße
Ich finde die Frage schon ganz interessant. Immerhin ist es bei jeder anderen (non-private & non-pure-virtual) Methode auch so, dass sie "automatisch da ist", solange man sie nicht absichtlich versteckt oder überschreibt....
Da müsste das Argument eigentlich genauso gelten.Gruß,
Simon2.
-
Simon2 schrieb:
Ich finde die Frage schon ganz interessant. Immerhin ist es bei jeder anderen (non-private & non-pure-virtual) Methode auch so, dass sie "automatisch da ist", solange man sie nicht absichtlich versteckt oder überschreibt....
Okay, also nehmen wir an der Konstruktor von foo würde an bar vererbt. Dann hätte die Klasse bar einen Konstruktor foo::bar(int). Ein Konstruktor muss aber immer so heissen wie die Klasse die er konstruiert.
Oder, wir nehmen an der Konstruktor von foo würde an bar vererbt. Die Klasse bar hat mehrere non-triviale Member. Da wir aber den Konstruktor foo(int) von der Basis geerbt haben werden diese nicht konstruiert und hängen undefiniert herum.
Mir würden sicher noch einige weitere Gründe einfallen, warum man Konstruktoren (genausowenig wie Destruktoren) nicht erben können sollte, aber mir reicht schon der zweite

EDIT:
Die verflixten Wortfindungsstörungen...
-
LordJaxom schrieb:
Simon2 schrieb:
Ich finde die Frage schon ganz interessant. Immerhin ist es bei jeder anderen (non-private & non-pure-virtual) Methode auch so, dass sie "automatisch da ist", solange man sie nicht absichtlich versteckt oder überschreibt....
Okay, also nehmen wir an der Konstruktor von foo würde an bar vererbt. Dann hätte die Klasse bar einen Konstruktor foo::bar(int). Ein Konstruktor muss aber immer so heissen wie die Klasse die er konstruiert.
Oder, wir nehmen an der Konstruktor von foo würde an bar vererbt. Die Klasse bar hat mehrere non-triviale Member. Da wir aber den Konstruktor foo(int) von der Basis geerbt haben werden diese nicht konstruiert und hängen undefiniert herum.
Mir würden sicher noch einige weitere Gründe einfallen, warum man Konstruktoren (genausowenig wie Destruktoren) nicht erben können sollte, aber mir reicht schon der zweite

EDIT:
Die verflixten Wortfindungsstörungen...Noch schlimmer: Konstruktoren haben nichtmal Namen!

-
LordJaxom schrieb:
Dann hätte die Klasse bar einen Konstruktor foo::bar(int). Ein Konstruktor muss aber immer so heissen wie die Klasse die er konstruiert.
Oder, wir nehmen an der Konstruktor von foo würde an bar vererbt. Die Klasse bar hat mehrere non-triviale Member. Da wir aber den Konstruktor foo(int) von der Basis geerbt haben werden diese nicht konstruiert und hängen undefiniert herum.
Stimmt. Der Default-Konstruktor-Mechanismus müsste intelligenter sein...
-
LordJaxom schrieb:
...Ein Konstruktor muss aber immer so heissen wie die Klasse die er konstruiert....
Naja, dass es sich um einen Konstruktor handelt, kann dem Compiler durchaus bewusst sein, so dass er sich um diese Konsistenz selbst kümmern kann.
erst Recht, wenn gelten sollDavid_pb schrieb:
...Noch schlimmer: Konstruktoren haben nichtmal Namen!

Das zweite Argument gilt für jede "non-const-Funktion" ebenso. Natürlich ist der Programmierer der abgeleiteten Klasse für die Datenkonsistenz immer verantwortlich (weswegen man sehr gut überlegen sollte, ob man Funktionen überschreiben muß oder nicht).
Wie gesagt: Ich habe kein konkretes Problem damit, aber so recht zwingend erscheint es mir (bislang) nicht.Gruß,
Simon2.
-
Simon2 schrieb:
Wie gesagt: Ich habe kein konkretes Problem damit, aber so recht zwingend erscheint es mir (bislang) nicht.
Zu dem zweiten von mir genannten Grund hast Du Dich nicht geäußert. IMHO macht es das sehr zwingend. Eine andere Sache wäre es wenn der Compiler einen Konstruktor generiert der einen Parameter hat und den Basisklassenkonstruktor mit einem Parameter implizit aufruft. Das hat dann aber nichts mehr mit erben zu tun.
-
LordJaxom schrieb:
...
Zu dem zweiten von mir genannten Grund hast Du Dich nicht geäußert...Hmmm, ich dachte, das hätte ich. Vielleicht hatte ich auch Dein Argument mißverstanden.
Nun gut, nächster Versuch:
Die Situation, dass "zusätzliche Attribute" nicht sauber initialisiert werden, taucht auch ohne "Konstruktorvererbung" auf.class A { string a, b; public: A(string const& s): a(s) {} // ganz ohne Vererbung habe ich b vergessen void init() { a="Jaxom"; b="Simon"; } }; class B : public A { string c; public: B(string const& s) : A(s) {} // Hier vergesse ich auch c // ... und wenn ich init() nicht "override" (wozu es eigentlich nicht da ist), auch dabei };Ergo: Durch eine "Ctor-Vererbung" hätte ich kein neues Problem geschaffen.
Gruß,
Simon2.
-
Simon2 schrieb:
A(string const& s): a(s) {} // ganz ohne Vererbung habe ich b vergessenHier wird für b der Standardkonstruktor von std::string aufgerufen.
-
LordJaxom schrieb:
Simon2 schrieb:
A(string const& s): a(s) {} // ganz ohne Vererbung habe ich b vergessenHier wird für b der Standardkonstruktor von std::string aufgerufen.
Ahaaa !!!

Jetzt weiß ich, worauf Du hinauswillst - und sehe auch das Problem.
Gut, da hätte man vermutlich was "drumherumdefinieren" können (so, dass auch in Fall eines "geerbten Konstruktors" für die neuen Elemente der StdCtor aufgefufen wird) .... aber ich sehe ein, dass sich niemand die Mühe macht, für diesen (vermutlich in 100% der Fälle ungewollten) Effekt so eine Sonderlocke zu definieren.
Außerdem wäre damit der Standard auch nicht "konsistenter" geworden.danke für die Aufklärung.
Gruß,
Simon2.