Hat das Erstellen eines Konstruktors mit mehreren Argumenten explicit
einen (nützlichen) Effekt?
Beispiel:
class A {
public:
explicit A( int b, int c ); // does explicit have any (useful) effect?
};
Antworten:
Bis C ++ 11 gibt es keinen Grund, explicit
einen Konstruktor mit mehreren Argumenten zu verwenden.
Das ändert sich in C ++ 11 aufgrund von Initialisierungslisten. Grundsätzlich erfordert die Kopierinitialisierung (aber keine direkte Initialisierung) mit einer Initialisierungsliste, dass der Konstruktor nicht markiert ist explicit
.
Beispiel:
struct Foo { Foo(int, int); };
struct Bar { explicit Bar(int, int); };
Foo f1(1, 1); // ok
Foo f2 {1, 1}; // ok
Foo f3 = {1, 1}; // ok
Bar b1(1, 1); // ok
Bar b2 {1, 1}; // ok
Bar b3 = {1, 1}; // NOT OKAY
explicit
. Ich persönlich würde mir nicht die Mühe machen, Konstruktoren mit mehreren Argumenten herzustellen explicit
.
Sie würden bei der Klammerinitialisierung darauf stoßen (zum Beispiel in Arrays).
struct A {
explicit A( int b, int c ) {}
};
struct B {
B( int b, int c ) {}
};
int main() {
B b[] = {{1,2}, {3,5}}; // OK
A a1[] = {A{1,2}, A{3,4}}; // OK
A a2[] = {{1,2}, {3,4}}; // Error
return 0;
}
Die hervorragenden Antworten von @StoryTeller und @Sneftel sind der Hauptgrund. IMHO, dies ist jedoch sinnvoll (zumindest mache ich das), um spätere Änderungen am Code zu überprüfen. Betrachten Sie Ihr Beispiel:
class A {
public:
explicit A( int b, int c );
};
Dieser Code profitiert nicht direkt davon explicit
.
Einige Zeit später beschließen Sie, einen Standardwert für hinzuzufügen c
, sodass dieser wie folgt lautet:
class A {
public:
A( int b, int c=0 );
};
Dabei konzentrieren Sie sich auf den c
Parameter - im Nachhinein sollte er einen Standardwert haben. Sie konzentrieren A
sich nicht unbedingt darauf, ob selbst implizit konstruiert werden soll. Leider macht diese Änderung wieder explicit
relevant.
Um zu vermitteln, dass es sich um einen Ctor handelt explicit
, kann es sich lohnen, dies beim ersten Schreiben der Methode zu tun.
explicit
dass das schon immer da war, und der technische Support wird mit Anrufen über diese Änderung überschwemmt sein und Stunden damit verbringen, zu erklären, dass dies explicit
nur Lärm war und dass das Entfernen harmlos ist. Persönlich bin ich nicht sehr gut darin, die Zukunft vorherzusagen; Es ist schwer genug zu entscheiden, wie eine Benutzeroberfläche jetzt aussehen soll .
Hier sind meine fünf Cent für diese Diskussion:
struct Foo {
Foo(int, double) {}
};
struct Bar {
explicit Bar(int, double) {}
};
void foo(const Foo&) {}
void bar(const Bar&) {}
int main(int argc, char * argv[]) {
foo({ 42, 42.42 }); // valid
bar({ 42, 42.42 }); // invalid
return 0;
}
Wie Sie leicht sehen können, wird explicit
verhindert , dass die Initialisierungsliste zusammen mit der bar
Funktion verwendet wird, da der Konstruktor von struct Bar
als deklariert ist explicit
.