unidades que pulgadas programa pies pesos para metros medida kilometros dolares convierta convertir conversiones centimetros c++ type-conversion implicit-conversion

c++ - que - programa para convertir unidades de medida en c#



Secuencia de conversiones definida por el usuario (3)

compilador no ejecuta la conversión consecutiva definida por el usuario

Tu maestro tiene razón. En el ejemplo de código, significa que Myclass no se puede convertir a Myclass1 cuando se asigna en:

Myclass2 m2 = Myclass{};

Debido a que el constructor espera Myclass1 al crear Myclass2 , el compilador no puede convertir de forma consecutiva Myclass a Myclass1 y luego usarlo para crear Myclass2 . Pero si tienes la siguiente línea:

Myclass1 m2 = Myclass{};

Funcionará, porque el constructor de Myclass1 toma a Myclass como argumento.

Actualizar:

Puedes preguntar por qué funciona esto:

Myclass2 m2 {Myclass{}};

Porque en este caso, se llama al constructor y la conversión se puede realizar de forma implícita a menos que declare Myclass1 como explicit lo que fallará en la compilación del código (gracias Fureeish por el recordatorio), pero en:

Myclass2 m2 = Myclass{};

Es como llamar a copy-constructor que necesita referencia. así que si lo escribes así, funcionará:

Myclass2 m2 = Myclass1(Myclass{});

Como mencionó , Myclass2 m2 = Myclass{}; es aceptado por VS 2017 si el modo de conformidad (/ permisivo-) no está activado.

Antes de estudiar la palabra clave explicit , mi profesor dijo: "el compilador no ejecuta la conversión consecutiva definida por el usuario". Si es verdad, ¿hay algún error en mi código? ¿O he entendido mal a mi maestro? Estoy trabajando en VS2017.

#include<iostream> #include <string> class Myclass { public: Myclass() { std::cout << "Myclass" << std::endl; } }; class Myclass1 { public: Myclass1(Myclass m) { std::cout << "Myclass1" << std::endl; } }; class Myclass2{ public: Myclass2(Myclass1 m) { std::cout << "Myclass2" << std::endl; } }; int main() { Myclass2 m2 = Myclass{}; }


La línea

Myclass2 m2 = Myclass{};

significa copia-inicialización . Citando cppreference.com :

Si T es un tipo de clase, y la versión no calificada de CV del tipo de other no es T o se deriva de T [...] las secuencias de conversión definidas por el usuario que pueden convertir del tipo de other a T [... ] se examinan y se selecciona el mejor a través de la resolución de sobrecarga.

Citando further :

Una conversión definida por el usuario consta de cero o un constructor de argumento único no explícito o una llamada a la función de conversión no explícita.

Entonces, Myclass2 m2 = Myclass{}; no es aceptable porque implicaría dos conversiones definidas por el usuario.

Ahora echemos un vistazo a

Myclass2 m2 {Myclass{}};

Sugirió en la respuesta de Afshin . Esto es una inicialización directa . Las reglas son different :

Los constructores de T se examinan y la mejor coincidencia se selecciona por resolución de sobrecarga. Luego se llama al constructor para inicializar el objeto.

El constructor de Myclass2 acepta Myclass1 , y necesita una conversión definida por el usuario para obtener Myclass1 de Myclass . Por lo tanto, se compila.

Tenga en cuenta que en VS la iniciación de la copia se trata como la iniciación directa si el modo de conformidad ( /premissive- ) no está activado (por defecto). Entonces, VS acepta Myclass2 m2 = Myclass{}; tratándolo como iniciación directa . Vea este documento para ejemplos.


Las otras respuestas están enterrando el lede: el código que has escrito no es válido . MSVC lo acepta de forma predeterminada, pero MSVC está equivocado al hacerlo. Puede obligar a MSVC a ser más estricto usando el interruptor de línea de comandos /permissive- . ( Deberías usar ese interruptor ).

Otros compiladores (GCC, clang), lo rechazan.

Todos los compiladores aceptan el código una vez que cambia la inicialización de la copia para dirigir la inicialización como se muestra en las otras respuestas.