2010-09-15 10 views
7

Wenn man eine öffentliche API entwirft, ist es eine gute Übung, den Konstruktor explizit zu machen?Ist es eine gute Praxis, den Konstruktor explizit zu machen?

class A { 
public: 
    //explicit A(int i){} 
    A(int i){} 
}; 

void fun(const A& a) {} 

int main() { 
    // If I use explicit for A constructor, I can prevent this mistake. 
    // (Or shall I call it as feature?) 
    fun(10); 
} 

Oder soll ich implizite Konvertierung zulassen, damit Benutzer meine API mit weniger Typisierung aufrufen kann?

Antwort

9

Der Konstruktor sollte explizit sein, es sei denn, eine implizite Umwandlung ergibt semantisch Sinn (z. B. was bedeutet die Umwandlung einer int in eine A?). Weniger Tippen sollte nicht das Kriterium sein, um diese Entscheidung zu leiten. Denken Sie an die Lesbarkeit (die das Hauptargument für das implizite Casting ist) und daran, wie gut Ihr Code zu verstehen ist. Eine implizite Besetzung, die nicht intuitiv ist, wird die Leser des Codes ihren Kopf kratzen lassen.

P.S .: Ich kann mir im Moment kein gutes Beispiel einfallen lassen, daher wird jede Hilfe geschätzt.

+7

Beispiel für implizite Konvertierung: alles numberlike (z.eine Bignum-Bibliothek oder eine Date/Time-Bibliothek) - gegen implizite Konvertierung: Betrachten Sie einfach die Klasse 'std :: vector', die mit einer initialen Größe initialisiert werden kann. –

+1

Dem stimme ich zu. In IME gibt es selten einen Fall, in dem implizites Casting gewünscht wird. Wenn Sie sich auf der expliziten Seite irren, wird kein Schaden angerichtet, indem Benutzer zu einigen weiteren Tastenanschlägen gezwungen werden. – sbi

+0

Als Beispiel: implizite Konvertierung von Double zu Complex über 'complex (double re, double im = 0)' macht Sinn, aber die Umwandlung von int in Vektor über 'vector (int size)' nicht. –

1

Explizite Konstruktoren werden in Klassen verwendet, die signifikante Ressourcen wie Speicher, Konstruktionszeit usw. verbrauchen, um zu verhindern, dass Benutzer Instanzen solcher Klassen versehentlich erstellen. Es liegt an Ihnen zu entscheiden, ob Ihre Klasse "schwer" genug ist, um explizite Konstruktoren zu verwenden.

+5

Unbeabsichtigtes Casting kann fatal sein, selbst wenn das Objekt nicht teuer zu erstellen ist. –

+0

@ Space_C0wb0y: Zufälliges Casting ist deine eigene Schuld für das versehentliche Tippen eines Cast. Zufällige implizite Konvertierung ist hier sicherlich das Thema. –

+0

@Steve Jessop: Sie haben Recht. –

1

Es hängt von den Kosten ab, die semantisch und Leistung beteiligt sind. Wenn die Erstellung Ihrer Klasse teuer ist, sollten Sie verhindern, dass sie versehentlich instanziiert wird. Wenn es eine billige Klasse zu erstellen ist, kann die implizite Konstruktion die Arbeit für den API-Benutzer erheblich vereinfachen.

+1

Dies schließt die Mehrdeutigkeiten und potenziell unerwünschten, nicht-sinnlichen Konvertierungen, die sonst passieren können, nicht ein. –

4

This ist das, was ich in einem resonse von „Daniel Krügler“ gefunden

Wenn wir auf C++ von heute zu entwerfen begonnen hätte, es ist eine gute Chance, dass alle Konstrukteure und Konvertierungsfunktionen waren "explizit" standardmäßig, aber ein Benutzer könnte die "implizit" machen. Leider kann die Zeit nicht zurückgedreht werden und wir müssen mit den aktuellen Stand leben. Dies bedeutet, dass wir implizite Konstruktoren (mit Ausnahme des Copy/Move-Konstruktors) vorsichtig sein müssen. Es ist eine sicherere Regel, Konstruktoren explizit zu machen, wo eine Form der Umwandlung beteiligt ist (d. H. Jeder Konstruktor mit ein Argument Typ U unterscheidet sich von dem tatsächlichen Typ T ).

+2

Wer ist Daniel Krügler? –

+0

@Yan Cheng CHEOK: Ich denke, er ist Teil des C++ Standards Committee (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010) – Chubsdad

5

Ja, standardmäßig sollte jeder Konstruktor, der mit einem Argument aufgerufen werden kann, explizit sein. Nach dieser Regel werden kleine Fehler vermieden, die extrem schwer zu finden sind.

Natürlich gibt es Ausnahmen von dieser Regel:

  • Implizite Konvertierung könnte wünschenswert sein, wenn Ihre Klasse die Semantik ein Wrapper um den einen Parameter der Typ hat.

  • Kopierkonstruktoren sollten nicht explizit sein (sonst verlieren Sie die Möglichkeit für Pass-by-Value-Aufrufe).

+0

+1, würde aber Glaubwürdigkeit hinzufügen, wenn Du hast die Käfer illustriert. –

Verwandte Themen