Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
'inicializando' : não é possível converter de 'type1' para 'type2'
'conversão' : não é possível converter de 'tipo1' para 'tipo2'
Observações
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.
O compilador gera C2440 quando não pode converter de um tipo para outro, implicitamente ou usando o cast especificado ou operador de conversão. Há muitas maneiras de gerar esse erro. Listamos alguns comuns na seção Exemplos.
Exemplos
Os literais de cadeia de caracteres C++ são const
C2440 pode 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 é definida. Em C, o tipo de uma cadeia de caracteres literal é um array de char, mas em C++, é um array de const char. Este exemplo gera 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
}
Os literais C++20 u8 são const char8_t
Em C++20 ou sob /Zc:char8_t, um caractere literal UTF-8 ou cadeia de caracteres (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 C++17 e 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
Poderá ver C2440 se tentar converter um ponteiro para membro em 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);
}
};
Elenco de tipo indefinido
O compilador emite C2440 se você tentar converter a partir de um tipo que é apenas declarado para frente, mas não definido. Este exemplo gera 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 pela mensagem Incompatible calling conventions for UDT return value. Um UDT é um tipo definido pelo usuário, como uma classe, structou 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, há primeiro declarações antecipadas para um struct e para uma função que retorna o struct. O compilador assume que o struct usa a convenção de chamada C++. Em seguida, está a struct definição, que usa a convenção de chamada C por padrão. Como o compilador não conhece a convenção de chamada de struct até terminar de ler o struct completo, a convenção de chamada para o struct no tipo de retorno de get_c2 também é assumida como C++.
O struct é seguido por outra declaração de função que retorna o struct. Neste ponto, o compilador reconhece 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 struct definição. 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 do 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
C2440 também pode ocorrer se 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
C2440 também pode ocorrer para 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 User-Defined conversões (C++/CLI)). Este exemplo gera 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);
}
System::Array Criação
C2440 também pode ocorrer ao tentar criar uma instância de uma matriz em C++/CLI cujo tipo é um Array. Para obter mais informações, consulte 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
C2440 também pode ocorrer devido a alterações no recurso de atributos. O exemplo a seguir gera C2440.
// c2440f.cpp
// compile with: /LD
[ module(name="PropDemoLib", version=1.0) ]; // C2440
// try the following line instead
// [ module(name="PropDemoLib", version="1.0") ];
Extensões de componentes para baixo moldes
O compilador Microsoft C++ não permite mais que o const_cast operador faça downcast quando se compila código-fonte em /clr.
Para resolver este C2440, use o operador de molde correto. Para obter mais informações, consulte Operadores de transmissão.
Este exemplo gera 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 na correspondência ao modelo de conformidade
C2440 pode ocorrer devido a alterações de conformidade no compilador do Visual Studio 2015 Update 3. Anteriormente, o compilador tratava incorretamente certas expressões distintas como o mesmo tipo ao identificar uma correspondência de modelo para uma static_cast operação. Agora, o compilador distingue os tipos corretamente, e o código que dependia do comportamento anterior static_cast é quebrado. Para corrigir este problema, altere o argumento do template para corresponder ao tipo de parâmetro do template ou use um casting ao estilo C.
Este exemplo gera 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 erro pode aparecer no código ATL que usa a SINK_ENTRY_INFO macro definida em <atlcom.h>.
Inicialização da lista de cópia
O Visual Studio 2017 e posterior geram corretamente erros de compilador relacionados à criação de objetos usando listas de inicializadores. Esses erros não foram detetados no Visual Studio 2015 e podem levar a falhas ou comportamento de tempo de execução indefinido. Em C++17 copy-list-initialization, o compilador é obrigado a considerar um construtor explícito para resolução de sobrecarga, mas deve gerar um erro se essa sobrecarga for realmente escolhida.
O exemplo a seguir compila 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 construção de classes
No Visual Studio 2015, o compilador às vezes ignora incorretamente o qualificador cv ao gerar um objeto de classe por meio de uma chamada de construtor. Esse defeito pode potencialmente causar uma falha ou um comportamento de tempo de execução inesperado. O exemplo a seguir compila no Visual Studio 2015, mas gera um erro de compilador no Visual Studio 2017 e posterior:
struct S
{
S(int);
operator int();
};
int i = (const S)0; // error C2440
Para corrigir o erro, declare o operador int() como const.