Verketten von Konstruktoren in C++
-
Hallo zusammen
bin gerade am umsteigen von Java in C++.
Kann man wie in Java Konstruktoren verketten? Das heist z.B in einem überladenen Konstruktor den Standartkonstruktor wie eine normale Methode aufrufen. Man erspart sich so, dass doppelte schreiben des codes.Beispiel in Java:
public class myClass{ private int mZahl; //Konstruktor 1 public myClass(){ mZahl=null; //code //code } //Konstruktor 2 public myClass(int zahl){ this();//an dieser Stelle wird der Konstruktor 1 als Methode aufgerufen mZahl=zahl; } }
Ich hoffe das mir da jemand weiterhelfen kann, der sich mit java und c++ aukennt.
-
Hi,
in C++ gibt's sowas nicht. Dafür nimmt man dann eine eigene "init-Funktion".
struct myClass{ // bin hier mal faul bzgl. access int mZahl; //Konstruktor 1 myClass() { init(); } //Konstruktor 2 myClass(int zahl) { init(zahl); } void init(int zahl = 0) { // do something mZahl=zahl; } };
Das Beispiel mit dem initialisieren einer Membervariable ist allerding nicht so ideal. Dafürb gibt's einerseits defaultparameter und andereseits Initialisierungslisten:
struct myClass{ int mZahl; //Konstruktor 1 & 2 myClass(int zahl = 0) : mZahl(zahl){ ... } ... };
(aber ich verstehe schon, dass das hier nur ein Beispiel ist und es Dir eigentlich um den Rest des Codes geht)
Gruß,
Simon2.
-
Simon2 schrieb:
in C++ gibt's sowas nicht. Dafür nimmt man dann eine eigene "init-Funktion".
Vielleicht noch anzumerken wäre, dass im neuen C++ Standard dies enthalten sein wird.
Bis dahin hilft nur die init-Funkton oder Copy&Paste.Grüssli
-
Bis jetzt hatte ich zwar noch nie einen Fall, wo ich dieses Featur benötigt hätte... Aber dass es in C++09 vorhanden ist, schadet sicher auch nichts.
-
@Nexus: ich hatte den Fall schon öfters. Kommt nicht jeden Tag vor, das stimmt, aber hin und wieder schon.
Besonders nervt es wenn man alles in einer Klasse was nur im Ctor einmal gesetzt und dann nie verändert wird "const" machen will, dann geht der Trick mit der Init-Funktion nämlich nichtmehr
-
hustbaer schrieb:
Besonders nervt es wenn man alles in einer Klasse was nur im Ctor einmal gesetzt und dann nie verändert wird "const" machen will, dann geht der Trick mit der Init-Funktion nämlich nichtmehr
Da gibts dann einen anderen Trick - der allerdings im restlichen Klassengebrauch etwas mehr Schreibarbeit mit sich bringt:
class C { struct m_ { const int a; const std::string name; const Foo f; m_(std::string const& name, int param = 42) : a(param), name(name), f(12) {}; //init-"Ersatz" }; const m_ m; int something; public: C(std::string const& newname, int a, int b) : m(newname, a) { something = b; } C(std::string const& newname, float f) : m(newname) { something = static_cast<int>(std::floor(std::sqtr(f)); } // später Zugriff auf die konstanten Member mit m::xyz };
Man kann sich natürlich über Schönheit und Ästhetik des Ganzen streiten, aber grade wenn viele der lifetime-constants von nur wenigen oder garkeinen Konstruktorparametern abhängen spart man sich für die verschiedenen Ctoren die lange init-Liste. Und dass diese Konstanten immer mit einem m:: (oder auch c::) qualifiziert werden müssen kann man notfalls als Feature ähnlich ungarischer Notation verkaufen (das m_ machen ja eh viele hier...)
-
pumuckl schrieb:
...Man kann sich natürlich über Schönheit und Ästhetik des Ganzen streiten, aber grade wenn viele der lifetime-constants von nur wenigen oder garkeinen Konstruktorparametern abhängen spart man sich für die verschiedenen Ctoren die lange init-Liste. ...
Naja - aber die Länge der Initialisierungsliste war ja eigentlich gar nicht das Problem, sondern die Codedoppelung (und die Unmöglichkeit, const-Member in einer init() zu initialisieren).
Und die hast Du in Deinem nicht vermieden.
Wenn Du z.B. (was Gott verhindern möge) eine Klasse mit 30 Konstruktoren hast, musst Du 30 Initlisten pflegen; was natürlich ein wenig einfacher ist, wenn man nur einen "Sammler" dadrin hat, aber das Problem bleibt.
Aber eine "Konstruktorenverknüpfung" müsste man natürlich auch pflegen...hustbaer schrieb:
...Besonders nervt es wenn man alles in einer Klasse was nur im Ctor einmal gesetzt und dann nie verändert wird "const" machen will, dann geht der Trick mit der Init-Funktion nämlich nichtmehr
Das stimmt - und allein schon die Tatsache, dass man einen "Trick" benötigt (sei es nun per init() oder per Kapselung), finde ich unschön...
Ohne jetzt in die Sprachdiskussion einsteigen zu wollen, fand ich die Möglichkeit zur "Verkettung von Konstruktoren" ganz gut in Java (wenn auch schlecht umgesetzt).
Gruß,
Simon2.
-
Simon2 schrieb:
sondern die Codedoppelung (und die Unmöglichkeit, const-Member in einer init() zu initialisieren).
Und die hast Du in Deinem nicht vermieden.
Wenn Du z.B. (was Gott verhindern möge) eine Klasse mit 30 Konstruktoren hast, musst Du 30 Initlisten pflegen; was natürlich ein wenig einfacher ist, wenn man nur einen "Sammler" dadrin hat, aber das Problem bleibt.Stimmt. Den Konstruktor des geschachtelten Struct muss man in jedem einzelnen Ctor aufrufen. Was in etwa genausoviel Schreibaufwand (und Codeverdoppelung) ist wie in jedem Ctor ein init() aufzurufen. Oder nur marginal mehr Schreibaufwand als wenn man in 29 von den 30 Ctoren auf einen anderen Ctor der selben Klasse verweist
-
pumuckl schrieb:
...nur marginal mehr Schreibaufwand als wenn man in 29 von den 30 Ctoren auf einen anderen Ctor der selben Klasse verweist
Dass ich mir dessen bewusst war, kann man hieran sehen:
Simon2 schrieb:
...Aber eine "Konstruktorenverknüpfung" müsste man natürlich auch pflegen...
Insgesamt finde ich das Konzept "Ctor-Verknüpfung durch expliziten Aufruf" (sei es durch init(), wrapper oder tw. auch so, wie es java macht) nicht so dolle, wüsste allerdings auch nicht, wie man das besser machen könnte ...
Gruß,
Simon2.