c++ - que - Constructor explícito tomando múltiples argumentos
método constructor c++ (4)
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 función de
bar
porque el constructor de
struct Bar
se declara como
explicit
.
¿Hacer
explicit
un constructor con múltiples argumentos tiene algún efecto (útil)?
Ejemplo:
class A {
public:
explicit A( int b, int c ); // does explicit have any (useful) effect?
};
Hasta C ++ 11, sí, no hay razón para usar
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 copia (pero no la inicialización directa) con una lista de inicializador requiere que el constructor no se marque como
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
Las excelentes respuestas de @StoryTeller y @Sneftel son la razón principal. Sin embargo, en mi humilde opinión, esto tiene sentido (al menos lo hago), como parte de futuras pruebas de cambios en el código. Considera tu 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 parámetro
c
; en retrospectiva, debe tener un valor predeterminado.
No necesariamente te estás enfocando en si
A
debería construirse implícitamente.
Desafortunadamente, este cambio hace
explicit
relevante nuevamente.
Entonces, para transmitir que un ctor es
explicit
, podría pagar hacerlo cuando se escribe el método por primera vez.
Te toparías 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;
}