Compartir vía


Error del compilador C2440

'inicializando': no se puede realizar la conversión de 'tipo1' a 'tipo2'
'conversión': no se puede realizar la conversión de 'tipo1' a 'tipo2'

El compilador no puede convertir implícitamente de *type1* a *type2* ni puede usar el operador de conversión especificado.

Comentarios

El compilador genera el error C2440 cuando no puede convertir un tipo en otro, ya sea implícitamente o usando el operador de conversión especificado. Hay muchas formas de producir este error. Hemos enumerado algunas comunes en la sección Ejemplos.

Ejemplos

Los literales de cadena de C++ son const

El error C2440 puede deberse a que intenta inicializar un elemento char* (o wchar_t*) no const usando un literal de cadena en código de C++, cuando está establecida la opción de conformidad del compilador /Zc:strictStrings. En C, el tipo de un literal de cadena es una matriz de char, pero en C++, es una matriz de const char. Este ejemplo genera el error C2440:

// C2440s.cpp
// Build: cl /Zc:strictStrings /W3 C2440s.cpp
// When built, the compiler emits:
// error C2440: 'initializing' : cannot convert from 'const char [5]'
// to 'char *'
//        Conversion from string literal loses const qualifier (see
// /Zc:strictStrings)

int main() {
   char* s1 = "test"; // C2440
   const char* s2 = "test"; // OK
}

Los literales u8 de C++20 son const char8_t

En C++20 o en /Zc:char8_t, un carácter o cadena literal UTF-8 (como u8'a' o u8"String") es de tipo const char8_t o const char8_t[N], respectivamente. En este ejemplo, se muestra cómo cambia el comportamiento del compilador entre C++17 y C++20:

// C2440u8.cpp
// Build: cl /std:c++20 C2440u8.cpp
// When built, the compiler emits:
// error C2440: 'initializing' : cannot convert from 'const char8_t [5]'
// to 'const char *'
// note: Types pointed to are unrelated; conversion requires
// reinterpret_cast, C-style cast or function-style cast)

int main() {
   const char* s1 = u8"test"; // C2440 under /std:c++20 or /Zc:char8_t, OK in C++17
   const char8_t* s2 = u8"test"; // OK under /std:c++20 or /Zc:char8_t, C4430 in C++17
   const char* s3 = reinterpret_cast<const char*>(u8"test"); // OK
}

Puntero a miembro

Es posible que se encuentre el error C2440 si intenta convertir un puntero a miembro en void*. El ejemplo siguiente genera el error C2440:

// C2440.cpp
class B {
public:
   void  f(){;}

   typedef void (B::*pf)();

   void f2(pf pf) {
       (this->*pf)();
       void* pp = (void*)pf;   // C2440
   }

   void f3() {
      f2(f);
   }
};

Conversión de tipo no definido

El compilador emite el error C2440 si intenta convertir un tipo que solo tiene una declaración adelantada pero no está definido. Este ejemplo genera el error C2440:

// c2440a.cpp
struct Base { }; // Defined

struct Derived; // Forward declaration, not defined

Base * func(Derived * d) {
    return static_cast<Base *>(d); // error C2440: 'static_cast' : cannot convert from 'Derived *' to 'Base *'
}

Convención de llamada incompatible

Los errores C2440 de las líneas 15 y 16 del ejemplo siguiente se califican con el mensaje Incompatible calling conventions for UDT return value. Un UDT es un tipo definido por el usuario, como una clase, un struct o una unión. Estos tipos de errores de incompatibilidad se producen cuando la convención de llamada de un UDT especificado en el tipo de valor devuelto de una declaración adelantada entra en conflicto con la convención de llamada real del UDT y cuando hay un puntero de función implicado.

En el ejemplo, primero hay declaraciones adelantadas para un struct y para una función que devuelve struct. El compilador supone que struct usa la convención de llamada de C++. A continuación se muestra la definición del struct, que usa la convención de llamada de C de forma predeterminada. Dado que el compilador no conoce la convención de llamada del struct hasta que termina de leer todo el struct, también se supone que la convención de llamada para el struct en el tipo de valor devuelto de get_c2 es la de C++.

El struct va seguido de otra declaración de función que devuelve struct. En este momento, el compilador sabe que la convención de llamada del struct es la de C++. Del mismo modo, el puntero de función, que devuelve el struct, se define después de la definición del struct. El compilador ahora sabe que el struct usa la convención de llamada de C++.

Para resolver errores C2440 causados por convenciones de llamada incompatibles, declare funciones que devuelvan un UDT después de la definición del UDT.

// C2440b.cpp
struct MyStruct;

MyStruct get_c1();

struct MyStruct {
   int i;
   static MyStruct get_C2();
};

MyStruct get_C3();

typedef MyStruct (*FC)();

FC fc1 = &get_c1;   // C2440, line 15
FC fc2 = &MyStruct::get_C2;   // C2440, line 16
FC fc3 = &get_C3;

class CMyClass {
public:
   explicit CMyClass( int iBar)
      throw()   {
   }

   static CMyClass get_c2();
};

int main() {
   CMyClass myclass = 2;   // C2440
   // try one of the following
   // CMyClass myclass{2};
   // CMyClass myclass(2);

   int *i;
   float j;
   j = (float)i;   // C2440, cannot cast from pointer to int to float
}

Asignación de cero a un puntero interior

El error C2440 también puede producirse si se asigna cero a un puntero interior:

// C2440c.cpp
// compile with: /clr
int main() {
   array<int>^ arr = gcnew array<int>(100);
   interior_ptr<int> ipi = &arr[0];
   ipi = 0;   // C2440
   ipi = nullptr;   // OK
}

Conversiones definidas por el usuario

El error C2440 también puede producirse por un uso incorrecto de una conversión definida por el usuario. Por ejemplo, cuando se ha definido un operador de conversión como explicit, el compilador no puede usarlo en una conversión implícita. Para obtener más información sobre las conversiones definidas por el usuario, consulte Conversiones definidas por el usuario (C++/CLI). Este ejemplo genera el error C2440:

// C2440d.cpp
// compile with: /clr
value struct MyDouble {
   double d;
   // convert MyDouble to Int32
   static explicit operator System::Int32 ( MyDouble val ) {
      return (int)val.d;
   }
};

int main() {
   MyDouble d;
   int i;
   i = d;   // C2440
   // Uncomment the following line to resolve.
   // i = static_cast<int>(d);
}

Creación de System::Array

El error C2440 también puede producirse si se intenta crear una instancia de una matriz en C++/CLI cuyo tipo es Array. Para más información, consulte Matrices. El ejemplo siguiente genera el error C2440:

// C2440e.cpp
// compile with: /clr
using namespace System;
int main() {
   array<int>^ intArray = Array::CreateInstance(__typeof(int), 1);   // C2440
   // try the following line instead
   // array<int>^ intArray = safe_cast<array<int> ^>(Array::CreateInstance(__typeof(int), 1));
}

Atributos

El error C2440 también puede producirse debido a cambios en la característica de atributos. El ejemplo siguiente genera el error C2440.

// c2440f.cpp
// compile with: /LD
[ module(name="PropDemoLib", version=1.0) ];   // C2440
// try the following line instead
// [ module(name="PropDemoLib", version="1.0") ];

Conversión de extensiones de componentes a tipos heredados

El compilador de Microsoft C++ ya no permite que el operador const_cast convierta a tipos heredados cuando se compila código fuente con /clr.

Para resolver este error C2440, use el operador de conversión correcto. Si desea obtener más información, consulte Operadores de conversión.

Este ejemplo genera el error C2440:

// c2440g.cpp
// compile with: /clr
ref class Base {};
ref class Derived : public Base {};
int main() {
   Derived ^d = gcnew Derived;
   Base ^b = d;
   d = const_cast<Derived^>(b);   // C2440
   d = dynamic_cast<Derived^>(b);   // OK
}

Cambios en la coincidencia de plantillas por motivos de conformidad

El error C2440 puede producirse debido a cambios por motivos de conformidad en el compilador de Visual Studio 2015 Update 3. Antes el compilador trataba incorrectamente ciertas expresiones distintas como si fuesen del mismo tipo al identificar una coincidencia de plantilla para una operación static_cast. Ahora el compilador distingue los tipos correctamente y se interrumpe el código que se basaba en el comportamiento de static_cast anterior. Para corregir este problema, cambie el argumento de plantilla para que coincida con el tipo de parámetro de plantilla, o bien use una conversión reinterpret_cast o del estilo de C.

Este ejemplo genera el error C2440:

// c2440h.cpp

template<int *a>
struct S1 {};

int g;
struct S2 : S1<&g> {
};

int main()
{
    S2 s;
    static_cast<S1<&*&g>>(s); // C2440 in VS 2015 Update 3
    // This compiles correctly:
    // static_cast<S1<&g>>(s);
}

Este error puede aparecer en el código ATL que usa la macro SINK_ENTRY_INFO definida en <atlcom.h>.

Inicialización de lista de copia

Visual Studio 2017 y versiones posteriores genera correctamente errores del compilador relacionados con la creación de objetos usando listas de inicializadores. Estos errores no se detectaban en Visual Studio 2015 y podían provocar bloqueos o un comportamiento indefinido en tiempo de ejecución. En la inicialización de lista de copia de C++17, el compilador debe tener en cuenta un constructor explícito para la resolución de la sobrecarga, pero debe generar un error si se elige realmente esa sobrecarga.

El siguiente código se compila en Visual Studio 2015, pero no en Visual Studio 2017.

// C2440j.cpp
struct A
{
    explicit A(int) {}
    A(double) {}
};

int main()
{
    const A& a2 = { 1 }; // error C2440: 'initializing': cannot
                         // convert from 'int' to 'const A &'
}

Para corregir el error, use la inicialización directa:

// C2440k.cpp
struct A
{
    explicit A(int) {}
    A(double) {}
};

int main()
{
    const A& a2{ 1 };
}

Calificadores cv en la constructión de clases

En Visual Studio 2015, el compilador a veces omite incorrectamente el calificador cv al generar un objeto de clase mediante una llamada al constructor. Este defecto puede causar un bloqueo o un comportamiento inesperado en tiempo de ejecución. El ejemplo siguiente se compila en Visual Studio 2015, pero se genera un error del compilador en Visual Studio 2017:

struct S
{
    S(int);
    operator int();
};

int i = (const S)0; // error C2440

Para corregir el error, declare el operador int() como const.