
Stormenet
Als ein C# Entwickler Ich bin es gewohnt, Konstruktoren zu durchlaufen:
class Test {
public Test() {
DoSomething();
}
public Test(int count) : this() {
DoSomethingWithCount(count);
}
public Test(int count, string name) : this(count) {
DoSomethingWithName(name);
}
}
Gibt es eine Möglichkeit, dies in C++ zu tun?
Ich habe versucht, den Klassennamen aufzurufen und das Schlüsselwort „this“ zu verwenden, aber beides schlägt fehl.

JohnIdol
C++11: Ja!
C++11 und höher hat dieselbe Funktion (genannt Konstruktoren delegieren).
Die Syntax unterscheidet sich geringfügig von C#:
class Foo {
public:
Foo(char x, int y) {}
Foo(int y) : Foo('a', y) {}
};
C++03: Nein
Leider gibt es in C++03 keine Möglichkeit, dies zu tun, aber es gibt zwei Möglichkeiten, dies zu simulieren:
-
Sie können zwei (oder mehr) Konstruktoren über Standardparameter kombinieren:
class Foo {
public:
Foo(char x, int y=0); // combines two constructors (char) and (char, int)
// ...
};
-
Verwenden Sie eine Init-Methode, um gemeinsamen Code zu teilen:
class Foo {
public:
Foo(char x);
Foo(char x, int y);
// ...
private:
void init(char x, int y);
};
Foo::Foo(char x)
{
init(x, int(x) + 7);
// ...
}
Foo::Foo(char x, int y)
{
init(x, y);
// ...
}
void Foo::init(char x, int y)
{
// ...
}
Sehen den C++FAQ-Eintrag als Referenz.

Kyrill Ka
Ja und Nein, je nachdem, welche Version von C++.
In C++03 können Sie einen Konstruktor nicht von einem anderen aufrufen (sogenannter delegierender Konstruktor).
Dies hat sich in C++11 (alias C++0x) geändert, wodurch die Unterstützung für die folgende Syntax hinzugefügt wurde:
(Beispiel entnommen aus Wikipedia)
class SomeType
{
int number;
public:
SomeType(int newNumber) : number(newNumber) {}
SomeType() : SomeType(42) {}
};

quadratisch
Ich glaube, Sie können einen Konstruktor von einem Konstruktor aufrufen. Es wird kompiliert und ausgeführt. Ich habe kürzlich gesehen, wie jemand dies getan hat, und es lief sowohl unter Windows als auch unter Linux.
Es macht einfach nicht was du willst. Der innere Konstruktor erstellt ein temporäres lokales Objekt, das gelöscht wird, sobald der äußere Konstruktor zurückkehrt. Sie müssten auch unterschiedliche Konstruktoren sein oder Sie würden einen rekursiven Aufruf erstellen.
Ref: https://isocpp.org/wiki/faq/ctors#init-methods

kchoose2
C++11: Jawohl!
C++11 und höher hat dieselbe Funktion (genannt Konstruktoren delegieren).
Die Syntax unterscheidet sich geringfügig von C#:
class Foo {
public:
Foo(char x, int y) {}
Foo(int y) : Foo('a', y) {}
};
C++03: Nein
Es ist erwähnenswert, dass Sie kann Rufen Sie den Konstruktor einer übergeordneten Klasse in Ihrem Konstruktor auf, z.
class A { /* ... */ };
class B : public A
{
B() : A()
{
// ...
}
};
Aber nein, Sie können keinen anderen Konstruktor derselben Klasse bis C++03 aufrufen.

Ben L
Im C++11ein Konstruktor kann eine andere Konstruktorüberladung aufrufen:
class Foo {
int d;
public:
Foo (int i) : d(i) {}
Foo () : Foo(42) {} //New to C++11
};
Darüber hinaus können Mitglieder auch so initialisiert werden.
class Foo {
int d = 5;
public:
Foo (int i) : d(i) {}
};
Dies sollte die Erstellung der Hilfsmethode für die Initialisierung überflüssig machen. Und es wird dennoch empfohlen, keine virtuellen Funktionen in den Konstruktoren oder Destruktoren aufzurufen, um die Verwendung von Membern zu vermeiden, die möglicherweise nicht initialisiert sind.
Wenn Sie böse sein wollen, können Sie den In-Place-Operator “new” verwenden:
class Foo() {
Foo() { /* default constructor deliciousness */ }
Foo(Bar myParam) {
new (this) Foo();
/* bar your param all night long */
}
};
Scheint bei mir zu funktionieren.
bearbeiten
Wie @ElvedinHamzagic betont, wird dieses Objekt möglicherweise nicht freigegeben, wenn Foo ein Objekt enthält, das Speicher zugewiesen hat. Das verkompliziert die Sache weiter.
Ein allgemeineres Beispiel:
class Foo() {
private:
std::vector<int> Stuff;
public:
Foo()
: Stuff(42)
{
/* default constructor deliciousness */
}
Foo(Bar myParam)
{
this->~Foo();
new (this) Foo();
/* bar your param all night long */
}
};
Sieht auf jeden Fall etwas weniger elegant aus. Die Lösung von @JohnIdol ist viel besser.

Scott Smith
Einfach gesagt, Sie können nicht vor C++11.
C++11 führt ein Konstruktoren delegieren:
Konstrukteur delegieren
Wenn der Name der Klasse selbst als Klassen-oder-Bezeichner in der Member-Initialisierer-Liste erscheint, dann darf die Liste nur aus diesem einen Member-Initialisierer bestehen; ein solcher Konstruktor wird als delegierender Konstruktor bezeichnet, und der Konstruktor, der vom einzigen Mitglied der Initialisiererliste ausgewählt wird, ist der Zielkonstruktor
In diesem Fall wird der Zielkonstruktor durch Überladungsauflösung ausgewählt und zuerst ausgeführt, dann kehrt das Steuerelement zum delegierenden Konstruktor zurück und sein Rumpf wird ausgeführt.
Delegierende Konstruktoren können nicht rekursiv sein.
class Foo {
public:
Foo(char x, int y) {}
Foo(int y) : Foo('a', y) {} // Foo(int) delegates to Foo(char,int)
};
Beachten Sie, dass ein delegierender Konstruktor ein Alles-oder-Nichts-Vorschlag ist; Wenn ein Konstruktor an einen anderen Konstruktor delegiert, darf der aufrufende Konstruktor keine anderen Member in seiner Initialisierungsliste haben. Dies ist sinnvoll, wenn Sie daran denken, const/reference-Elemente einmal und nur einmal zu initialisieren.
9980000cookie-checkKann ich in C++ einen Konstruktor von einem anderen Konstruktor aufrufen (Konstruktorverkettung durchführen)?yes
Verwenden
this
ODERauto
im angesprochenen Kontext wären interessante Schlüsselwörter für zukünftige Refactoring-Zwecke.– sergiol
29. Dezember 2015 um 16:13 Uhr