¿Hacer un constructor que tenga múltiples argumentos explicit
tiene algún efecto (útil)?
Ejemplo:
class A {
public:
explicit A( int b, int c ); // does explicit have any (useful) effect?
};
Respuestas:
Hasta C ++ 11, sí, no hay razón para usarlo explicit
en un constructor de múltiples argumentos.
Eso cambia en C ++ 11, debido a las listas de inicializadores. Básicamente, la inicialización de la copia (pero no la inicialización directa) con una lista de inicializadores requiere que el constructor no esté marcado explicit
.
Ejemplo:
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
. Personalmente, no me molestaría en hacer constructores de múltiples argumentos explicit
.
Se toparía con él para la inicialización de llaves (por ejemplo, en matrices)
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;
}
Las excelentes respuestas de @StoryTeller y @Sneftel son la razón principal. Sin embargo, en mi humilde opinión, esto tiene sentido (al menos yo lo hago), como parte de futuras pruebas de cambios posteriores al código. Considere su ejemplo:
class A {
public:
explicit A( int b, int c );
};
Este código no se beneficia directamente de explicit
.
Algún tiempo después, decide agregar un valor predeterminado para c
, por lo que se convierte en esto:
class A {
public:
A( int b, int c=0 );
};
Al hacer esto, se está enfocando en el c
parámetro; en retrospectiva, debería tener un valor predeterminado. No se está enfocando necesariamente en si A
debe construirse implícitamente. Lamentablemente, este cambio vuelve a explicit
ser relevante.
Entonces, para transmitir que un ctor es explicit
, podría ser útil hacerlo al escribir el método por primera vez.
explicit
ha estado allí desde siempre, y el soporte técnico se verá inundado de llamadas sobre ese cambio y pasará horas explicando que explicit
es solo ruido y que eliminarlo es inofensivo. Personalmente, no soy muy bueno para predecir el futuro; Ya es bastante difícil decidir cómo debería verse una interfaz ahora .
Aquí están mis cinco centavos para esta discusión:
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;
}
Como puede ver fácilmente, explicit
evita el uso de la lista de inicializadores junto con la bar
función porque el constructor de struct Bar
se declara como explicit
.