Partager via


Erreur du compilateur C2440

'initializing' : impossible de convertir de 'type1' en 'type2'
'conversion' : impossible de convertir de 'type1' en 'type2'

Le compilateur ne peut pas convertir implicitement vers *type2*, ou ne peut pas utiliser l’opérateur de *type1* cast ou de conversion spécifié.

Notes

Le compilateur génère C2440 lorsqu’il ne peut pas convertir d’un type en un autre, implicitement ou à l’aide de l’opérateur de conversion ou de cast spécifié. Il existe de nombreuses façons de générer cette erreur. Nous avons répertorié quelques exemples courants dans la section Exemples.

Exemples

Les littéraux de chaîne C++ sont const

C2440 peut être provoqué si vous tentez d’initialiser un non-constchar* (ou wchar_t*) à l’aide d’un littéral de chaîne dans le code C++, lorsque l’option /Zc:strictStrings de conformité du compilateur est définie. En C, le type d’un littéral de chaîne est tableau de char, mais en C++, il s’agit du tableau de const char. Cet exemple génère l’erreur 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
}

Les littéraux C++20 u8 sont const char8_t

En C++20 ou sous /Zc:char8_t, un caractère littéral ou une chaîne UTF-8 (tel que u8'a' ou u8"String") est de type const char8_t ou const char8_t[N], respectivement. Cet exemple montre comment le comportement du compilateur change entre C++17 et 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
}

Pointeur vers membre

Vous pouvez voir C2440 si vous tentez de convertir un pointeur en membre en void*. L’exemple suivant génère l’erreur 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 de type non défini

Le compilateur émet C2440 si vous tentez de convertir à partir d’un type qui n’est déclaré que par transfert, mais non défini. Cet exemple génère l’erreur 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 *'
}

Convention d’appel incompatible

Les erreurs C2440 sur les lignes 15 et 16 de l’exemple suivant sont qualifiées avec le Incompatible calling conventions for UDT return value message. Un UDT est un type défini par l’utilisateur, tel qu’une classe, structou une union. Ces types d’erreurs d’incompatibilité sont provoqués lorsque la convention d’appel d’un UDT spécifié dans le type de retour d’une déclaration de transfert est en conflit avec la convention d’appel réelle de l’UDT et lorsqu’un pointeur de fonction est impliqué.

Dans l’exemple, il existe d’abord des déclarations de transfert pour une struct fonction qui retourne le struct. Le compilateur part du principe que l’utilisation struct de la convention d’appel C++. Ensuite, la struct définition, qui utilise la convention d’appel C par défaut. Étant donné que le compilateur ne connaît pas la convention d’appel jusqu’à ce qu’il termine la lecture de struct l’intégralité struct, la convention d’appel pour le struct type de get_c2 retour est également supposée être C++.

L’objet struct est suivi d’une autre déclaration de fonction qui retourne le struct. À ce stade, le compilateur sait que la structconvention d’appel est C++. De même, le pointeur de fonction, qui retourne le struct, est défini après la struct définition. Le compilateur connaît maintenant les struct utilisations de la convention d’appel C++.

Pour résoudre les erreurs C2440 provoquées par des conventions d’appel incompatibles, déclarez des fonctions qui retournent un UDT après la définition 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
}

Affecter zéro au pointeur intérieur

C2440 peut également se produire si vous affectez zéro à un pointeur intérieur :

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

Conversions définies par l’utilisateur

C2440 peut également se produire pour une utilisation incorrecte d’une conversion définie par l’utilisateur. Par exemple, lorsqu’un opérateur de conversion a été défini comme explicit, le compilateur ne peut pas l’utiliser dans une conversion implicite. Pour plus d’informations sur les conversions définies par l’utilisateur, consultez Conversions définies par l’utilisateur (C++/CLI)). Cet exemple génère l’erreur 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 création

C2440 peut également se produire si vous essayez de créer une instance d’un tableau dans C++/CLI dont le type est un Array. Pour plus d’informations, consultez Tableaux. L’exemple suivant génère l’erreur 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));
}

Attributs

C2440 peut également se produire en raison de modifications apportées à la fonctionnalité d’attributs. L’exemple suivant génère l’erreur C2440.

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

Extensions de composant casts vers le bas

Le compilateur Microsoft C++ n’autorise plus l’opérateur à effectuer une conversion en panne lorsque vous compilez le const_cast code source sous /clr.

Pour résoudre ce C2440, utilisez l’opérateur de cast correct. Pour plus d’informations, consultez Opérateurs de cast.

Cet exemple génère l’erreur 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
}

Modifications de correspondance de modèle conformes

C2440 peut se produire en raison de modifications de conformité apportées au compilateur dans Visual Studio 2015 Update 3. Auparavant, le compilateur a traité incorrectement certaines expressions distinctes comme le même type lors de l’identification d’une correspondance de modèle pour une static_cast opération. Maintenant, le compilateur distingue correctement les types et le code qui s’appuie sur le comportement précédent static_cast est rompu. Pour résoudre ce problème, modifiez l’argument de modèle pour qu’il corresponde au type de paramètre du modèle ou utilisez un reinterpret_cast cast de style C.

Cet exemple génère l’erreur 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);
}

Cette erreur peut apparaître dans le code ATL qui utilise la SINK_ENTRY_INFO macro définie dans <atlcom.h>.

Copy-list-initialization

Visual Studio 2017 et versions ultérieures déclenchent correctement des erreurs de compilateur liées à la création d’objets à l’aide de listes d’initialiseurs. Ces erreurs n’ont pas été interceptées dans Visual Studio 2015 et peuvent entraîner des blocages ou un comportement d’exécution non défini. Dans C++17 copy-list-initialisation, le compilateur est tenu de prendre en compte un constructeur explicite pour la résolution de surcharge, mais doit déclencher une erreur si cette surcharge est réellement choisie.

L’exemple suivant compile dans Visual Studio 2015, mais pas dans 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 &'
}

Pour corriger l’erreur, utilisez une initialisation directe :

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

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

Qualificateurs cv dans la construction de la classe

Dans Visual Studio 2015, le compilateur ignore parfois à tort le qualificateur cv pendant la génération d’un objet de classe par le biais d’un appel de constructeur. Ce défaut peut entraîner un blocage ou un comportement d’exécution inattendu. L’exemple suivant compile dans Visual Studio 2015, mais génère une erreur de compilateur dans Visual Studio 2017 et versions ultérieures :

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

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

Pour corriger l’erreur, déclarez l’opérateur int() en tant que const.