Errore del compilatore C2440

'initializing': impossibile convertire da 'type1' a 'type2'
'conversion': impossibile convertire da 'type1' a 'type2'

Il compilatore non può convertire in modo implicito da *type1* a *type2*o non può usare l'operatore di cast o conversione specificato.

Osservazioni:

Il compilatore genera l'errore C2440 quando non può eseguire la conversione da un tipo a un altro, in modo implicito o usando l'operatore di conversione o cast specificato. Esistono molti modi per generare questo errore. Alcuni esempi sono stati elencati nella sezione Esempi.

Esempi

I valori letterali stringa C++ sono const

L'errore C2440 può essere causato se si tenta di inizializzare un valore nonconstchar* (o wchar_t*) usando un valore letterale stringa nel codice C++, quando viene impostata l'opzione /Zc:strictStrings di conformità del compilatore. In C, il tipo di un valore letterale stringa è una matrice di char, ma in C++, è una matrice di const char. Questo esempio genera l'errore 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
}

I valori letterali C++20 u8 sono const char8_t

In C++20 o in /Zc:char8_t, un carattere letterale UTF-8 o una stringa (ad esempio u8'a' o u8"String") è di tipo const char8_t o const char8_t[N], rispettivamente. Questo esempio illustra come cambia il comportamento del compilatore tra 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
}

Puntatore a membro

È possibile che venga visualizzato C2440 se si tenta di convertire un puntatore in membro in void*. L'esempio successivo genera l'errore 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);
   }
};

Cast di tipo non definito

Il compilatore genera L2440 se si tenta di eseguire il cast da un tipo dichiarato solo in avanti ma non definito. Questo esempio genera l'errore 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 *'
}

Convenzione di chiamata incompatibile

Gli errori C2440 nelle righe 15 e 16 dell'esempio successivo sono qualificati con il Incompatible calling conventions for UDT return value messaggio. Un tipo definito dall'utente è un tipo definito dall'utente, ad esempio una classe, structo un'unione. Questi tipi di errori di incompatibilità vengono causati quando la convenzione di chiamata di un tipo definito dall'utente specificato nel tipo restituito di una dichiarazione di inoltro è in conflitto con la convenzione di chiamata effettiva del tipo definito dall'utente e quando è coinvolto un puntatore a funzione.

Nell'esempio sono prima presenti dichiarazioni forward per un struct oggetto e per una funzione che restituisce .struct Il compilatore presuppone che struct usi la convenzione di chiamata C++. Successivamente è la struct definizione, che usa la convenzione di chiamata C per impostazione predefinita. Poiché il compilatore non conosce la convenzione di chiamata di struct fino a quando non termina la lettura dell'intero struct, si presuppone che anche la convenzione di chiamata per nel struct tipo restituito di get_c2 sia C++.

L'oggetto struct è seguito da un'altra dichiarazione di funzione che restituisce l'oggetto struct. A questo punto, il compilatore sa che la structconvenzione di chiamata di è C++. Analogamente, il puntatore alla funzione, che restituisce struct, viene definito dopo la struct definizione. Il compilatore conosce ora l'oggetto struct usa la convenzione di chiamata C++.

Per risolvere gli errori C2440 causati da convenzioni di chiamata incompatibili, dichiarare funzioni che restituiscono un tipo definito dall'utente dopo la definizione del tipo definito dall'utente.

// 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
}

Assegnare zero al puntatore interno

C2440 può verificarsi anche se si assegna zero a un puntatore interno:

// 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
}

Conversioni definite dall'utente

C2440 può verificarsi anche per un uso non corretto di una conversione definita dall'utente. Ad esempio, quando un operatore di conversione è stato definito come explicit, il compilatore non può usarlo in una conversione implicita. Per altre informazioni sulle conversioni definite dall'utente, vedere Conversioni definite dall'utente (C++/CLI). Questo esempio genera l'errore 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 creazione

C2440 può verificarsi anche se si tenta di creare un'istanza di una matrice in C++/CLI il cui tipo è .Array Per altre informazioni, vedere Matrici. L'esempio successivo genera l'errore 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));
}

Attributi

L'errore C2440 può verificarsi anche a causa delle modifiche apportate alla funzionalità attributi. L'esempio seguente genera l'errore C2440.

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

Cast inattivo delle estensioni dei componenti

Il compilatore Microsoft C++ non consente più all'operatore di arrestare il const_cast cast quando si compila il codice sorgente in /clr.

Per risolvere questo errore C2440, usare l'operatore cast corretto. Per altre informazioni, vedere Operatori di cast.

Questo esempio genera l'errore 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
}

Modifiche alle corrispondenze del modello conformi

L'errore C2440 può verificarsi a causa di modifiche di conformità al compilatore in Visual Studio 2015 Update 3. In precedenza, il compilatore considera erroneamente determinate espressioni distinte come lo stesso tipo quando si identifica una corrispondenza di modello per un'operazione static_cast . Ora il compilatore distingue correttamente i tipi e il codice basato sul comportamento precedente static_cast viene interrotto. Per risolvere questo problema, modificare l'argomento modello in modo che corrisponda al tipo di parametro del modello o usare un reinterpret_cast cast in stile C o .

Questo esempio genera l'errore 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);
}

Questo errore può essere visualizzato nel codice ATL che usa la SINK_ENTRY_INFO macro definita in <atlcom.h>.

Copy-list-initialization

Visual Studio 2017 e versioni successive generano correttamente errori del compilatore correlati alla creazione di oggetti usando elenchi di inizializzatori. Questi errori non sono stati rilevati in Visual Studio 2015 e potrebbero causare arresti anomali o comportamenti di runtime non definiti. In C++17 copy-list-initialization è necessario che il compilatore consideri un costruttore esplicito per la risoluzione dell'overload, ma deve generare un errore se tale overload viene effettivamente scelto.

L'esempio seguente viene compilato in Visual Studio 2015 ma non in 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 &'
}

Per correggere l'errore, usare l'inizializzazione diretta:

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

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

Qualificatori CV nella costruzione di classi

In Visual Studio 2015 il compilatore a volte ignora erroneamente il qualificatore CV quando genera un oggetto classe usando una chiamata al costruttore. Questo difetto può potenzialmente causare un arresto anomalo o un comportamento di runtime imprevisto. L'esempio seguente viene compilato in Visual Studio 2015, ma genera un errore del compilatore in Visual Studio 2017 e versioni successive:

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

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

Per correggere l'errore, dichiarare l'operatore int() come const.