Partilhar via


Erro do compilador C2440

'inicializando' : não é possível converter de 'tipo1' para 'tipo2'
'conversão' : não é possível converter de 'tipo1' para 'tipo2'

O compilador não pode converter implicitamente de *type1* para *type2*, ou não pode usar o operador de conversão ou a conversão especificada.

Comentários

O compilador gera o erro C2440 quando não pode converter de um tipo para outro, seja implicitamente ou usando o operador de conversão ou a conversão especificada. Há muitas maneiras de gerar esse erro. Listamos alguns erros comuns na seção Exemplos.

Exemplos

Literais de cadeia de caracteres C++ são const

O erro C2440 poderá ser causado se você tentar inicializar um não constchar* (ou wchar_t*) usando um literal de cadeia de caracteres no código C++, quando a opção /Zc:strictStrings de conformidade do compilador estiver definida. Em C, o tipo de literal de cadeia de caracteres é matriz de char, mas em C++, é matriz de const char. Este exemplo gera o erro 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
}

Literais u8 do C++20 são const char8_t

Em C++20 ou abaixo de /Zc:char8_t, um caractere literal ou cadeia de caracteres literal UTF-8 (como u8'a' ou u8"String") é do tipo const char8_t ou const char8_t[N], respectivamente. Este exemplo mostra como o comportamento do compilador muda entre o C++17 e o 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
}

Ponteiro para membro

Você poderá ver o erro C2440 se tentar converter um ponteiro em membro para void*. O próximo exemplo gera 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);
   }
};

Conversão de tipo indefinido

O compilador emitirá o erro C2440 se você tentar converter de um tipo que é encaminhado apenas declarado, mas não definido. Este exemplo gera o erro 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 *'
}

Convenção de chamada incompatível

Os erros C2440 nas linhas 15 e 16 do próximo exemplo são qualificados com a mensagem Incompatible calling conventions for UDT return value. Um UDT é um tipo definido pelo usuário, como uma classe, struct ou união. Esses tipos de erros de incompatibilidade são causados quando a convenção de chamada de um UDT especificado no tipo de retorno de uma declaração de encaminhamento entra em conflito com a convenção de chamada real do UDT e quando um ponteiro de função está envolvido.

No exemplo, primeiro há declarações de encaminhamento para um struct e para uma função que retorna o struct. O compilador pressupõe que o struct usa a convenção de chamada C++. Em seguida está a definição de struct, que usa a convenção de chamada C por padrão. Como o compilador não sabe a convenção de chamada do struct até concluir a leitura de todo o struct, a convenção de chamada para o struct no tipo de retorno do get_c2 também é considerada C++.

O struct é seguido por outra declaração de função que retorna o struct. Neste ponto, o compilador sabe que a convenção de chamada do struct é C++. Da mesma forma, o ponteiro da função, que retorna o struct, é definido após a definição de struct. O compilador agora sabe que struct usa a convenção de chamada C++.

Para resolver erros C2440 causados por convenções de chamada incompatíveis, declare funções que retornam um UDT após a definição de 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
}

Atribuir zero ao ponteiro interior

O erro C2440 também poderá ocorrer se você atribuir zero a um ponteiro 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
}

Conversões definidas pelo usuário

O erro C2440 também pode ocorrer em um uso incorreto de uma conversão definida pelo usuário. Por exemplo, quando um operador de conversão foi definido como explicit, o compilador não pode usá-lo em uma conversão implícita. Para obter mais informações sobre conversões definidas pelo usuário, consulte Conversões definidas pelo usuário (C++/CLI)). Este exemplo gera o erro 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);
}

Criação de System::Array

O erro C2440 também pode ocorrer se você tentar criar uma instância de uma matriz em C++/CLI cujo tipo é um Array. Saiba mais em Matrizes. O próximo exemplo gera 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

O erro C2440 também pode ocorrer devido a alterações no recurso de atributos. O exemplo a seguir gera o erro C2440.

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

Conversões de redução de extensões de componente

O compilador do Microsoft C++ não permite mais que o operador const_cast seja reduzido ao compilar o código-fonte em /clr.

Para resolver esse erro C2440, use o operador de conversão correto. Saiba mais em Operadores de conversão.

Este exemplo gera o erro 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
}

Alterações de correspondência de modelo de conformidade

O erro C2440 pode ocorrer devido a alterações de conformidade no compilador no Visual Studio 2015 Atualização 3. Anteriormente, o compilador tratava incorretamente determinadas expressões distintas como o mesmo tipo ao identificar uma correspondência de modelo para uma operação static_cast. Agora, o compilador distingue os tipos corretamente e o código que se baseava no comportamento static_cast anterior está corrompido. Para corrigir esse problema, altere o argumento do modelo para corresponder ao tipo de parâmetro do modelo ou use uma conversão de estilo C ou reinterpret_cast.

Este exemplo gera o erro 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);
}

Esse erro pode aparecer no código ATL que usa a macro SINK_ENTRY_INFO definida em <atlcom.h>.

Inicialização de lista de cópia

O Visual Studio 2017 e posteriores geram corretamente erros de compilador relacionados à criação de objetos usando listas de inicializadores. Esses erros não eram pegos no Visual Studio 2015 e podiam ocasionar falhas ou comportamento indefinido de runtime. Na inicialização de lista de cópia do C++17, o compilador deverá considerar um construct explícito para resolução de sobrecarga, mas deverá gerar um erro se essa sobrecarga for realmente escolhida.

O exemplo a seguir é compilado no Visual Studio 2015, mas não no 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 corrigir o erro, use a inicialização direta:

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

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

qualificadores CV na construction de classe

No Visual Studio 2015, às vezes, o compilador ignora incorretamente o qualificador CV ao gerar um objeto de classe por meio de uma chamada do constructor. Eventualmente, esse defeito pode gerar uma falha ou comportamento inesperado do runtime. O exemplo a seguir é compilado no Visual Studio 2015, mas gera um erro de compilador no Visual Studio 2017 e posteriores:

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

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

Para corrigir o erro, declare o operador int() como const.