Luego de de esta larga búsqueda de datos hemos podido solucionar esta interrogante que tienen ciertos de nuestros lectores. Te brindamos la solución y deseamos servirte de gran ayuda.
Solución:
La definición de un constructor de conversión es diferente entre C ++ 03 y C ++ 11. En ambos casos debe ser unexplicit
constructor (de lo contrario, no estaría involucrado en conversiones implícitas), pero para C ++ 03 también debe ser invocable con un solo argumento. Es decir:
struct foo
foo(int x); // 1
foo(char* s, int x = 0); // 2
foo(float f, int x); // 3
explicit foo(char x); // 4
;
Los constructores 1 y 2 son constructores de conversión en C ++ 03 y C ++ 11. El constructor 3, que debe tomar dos argumentos, es solo un constructor de conversión en C ++ 11. El último, el constructor 4, no es un constructor de conversión porque es explicit
.
-
C ++ 03: §12.3.1
Un constructor declarado sin el especificador de función
explicit
que se puede llamar con un solo parámetro especifica una conversión del tipo de su primer parámetro al tipo de su clase. Dicho constructor se denomina constructor de conversión. -
C ++ 11: §12.3.1
Un constructor declarado sin el especificador de función
explicit
especifica una conversión de los tipos de sus parámetros al tipo de su clase. Dicho constructor se denomina constructor de conversión.
¿Por qué se considera que los constructores con más de un parámetro son constructores de conversión en C ++ 11? Esto se debe a que el nuevo estándar nos proporciona una sintaxis útil para pasar argumentos y devolver valores usando listas-inicial-reforzadas. Considere el siguiente ejemplo:
foo bar(foo f)
return 1.0f, 5;
La capacidad de especificar el valor de retorno como lista-inicial-reforzada se considera una conversión. Esto usa el constructor de conversión para foo
eso toma un float
y un int
. Además, podemos llamar a esta función haciendo bar(2.5f, 10)
. Esto también es una conversión. Dado que son conversiones, tiene sentido que los constructores que utilizan sean conversión de constructores.
Es importante señalar, por lo tanto, que hacer que el constructor de foo
que toma un float
y un int
tener el explicit
El especificador de función detendría la compilación del código anterior. La nueva sintaxis anterior solo se puede usar si hay un constructor de conversión disponible para hacer el trabajo.
-
C ++ 11: §6.6.3:
A
return
declaración con un lista-inicial-reforzada inicializa el objeto o la referencia que se devolverá desde la función mediante la inicialización de la lista de copias (8.5.4) de la lista de inicializadores especificada.§8.5:
La inicialización que ocurre […] en el paso de la discusión […] se llama inicialización de copia.
§12.3.1:
Un constructor explícito construye objetos al igual que los constructores no explícitos, pero lo hace solo cuando se utiliza explícitamente la sintaxis de inicialización directa (8.5) o las conversiones (5.2.9, 5.4).
Conversión implícita con converting constructor
Hagamos el ejemplo de la pregunta más complejo.
class MyClass
public:
int a, b;
MyClass( int i )
MyClass( const char* n, int k = 0 )
MyClass( MyClass& obj )
Los dos primeros constructores son constructores de conversión. El tercero es un constructor de copia y, como tal, es otro constructor de conversión.
Un constructor de conversión permite la conversión implícita del tipo de argumento al tipo de constructor. Aquí, el primer constructor permite la conversión desde un int
a un objeto de clase MyClass
. El segundo constructor permite la conversión desde un string a un objeto de clase MyClass
. Y tercero … de un objeto de clase MyClass
a un objeto de clase MyClass
!
Para ser un constructor de conversión, el constructor debe tener un solo argumento (en el segundo, el segundo argumento tiene un valor predeterminado) y debe declararse sin la palabra clave explicit
.
Entonces, la inicialización en main puede verse así:
int main()
MyClass M = 1 ;
// which is an alternative to
MyClass M = MyClass(1) ;
MyClass M = "super" ;
// which is an alternative to
MyClass M = MyClass("super", 0) ;
// or
MyClass M = MyClass("super") ;
Constructores y palabras clave explícitas
Ahora, ¿y si hubiéramos usado el explicit
palabra clave?
class MyClass
public:
int a, b;
explicit MyClass( int i )
Entonces, el compilador no aceptaría
int main()
MyClass M = 1 ;
ya que esta es una conversión implícita. En cambio, tienes que escribir
int main()
MyClass M(1) ;
MyClass M = MyClass(1) ;
MyClass* M = new MyClass(1) ;
MyClass M = (MyClass)1;
MyClass M = static_cast(1);
explicit
La palabra clave siempre se debe usar para evitar la conversión implícita de un constructor y se aplica al constructor en una declaración de clase.
Un constructor de conversión es un constructor de un solo parámetro que se declara sin el especificador de función explícito. El compilador usa constructores de conversión para convertir objetos del tipo del primer parámetro al tipo de la clase del constructor de conversión.