Sdílet prostřednictvím


Chyba kompilátoru C2440

Inicializace: Nelze převést z type1 na type2.
'conversion' : nemůže převést z 'type1' na 'type2'

Kompilátor nemůže implicitně převést z *type1* operátoru na *type2*nebo nemůže použít zadaný operátor přetypování nebo převodu.

Poznámky

Kompilátor generuje C2440, pokud nemůže převést z jednoho typu na jiný, buď implicitně, nebo pomocí zadaného operátoru přetypování nebo převodu. Existuje mnoho způsobů, jak tuto chybu vygenerovat. V části Příklady jsme uvedli některé běžné.

Příklady

Řetězcové literály jazyka C++ jsou const

C2440 může být způsobeno, pokud se pokusíte inicializovat jinéconstchar* než (nebo wchar_t*) pomocí řetězcového literálu v kódu jazyka C++, pokud je nastavena možnost /Zc:strictStrings shody kompilátoru. V jazyce C je typ řetězcového literálu charpole , ale v jazyce C++ je to pole .const char Tato ukázka vygeneruje 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
}

Literály C++20 u8 jsou const char8_t

V jazyce C++20 nebo pod /Zc:char8_tje literál UTF-8 nebo řetězec (například u8'a' nebo u8"String") typu const char8_t nebo const char8_t[N]v uvedeném pořadí. Tato ukázka ukazuje, jak se mění chování kompilátoru mezi C++17 a 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
}

Ukazatel na člen

Může se zobrazit C2440, pokud se pokusíte převést ukazatel na člen na void*. Další ukázka vygeneruje 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);
   }
};

Přetypování nedefinovaného typu

Kompilátor generuje C2440, pokud se pokusíte přetypovat z typu, který je deklarován pouze vpřed, ale není definován. Tato ukázka vygeneruje 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 *'
}

Nekompatibilní konvence volání

Chyby C2440 na řádcích 15 a 16 dalšího vzorku jsou s zprávou Incompatible calling conventions for UDT return value kvalifikované. UDT je uživatelem definovaný typ, například třída, structnebo sjednocení. Tyto druhy chyb nekompatibility jsou způsobeny, když volání konvence UDT zadaného v návratovém typu předávací deklarace koliduje se skutečnou konvencí volání UDT a když je zapojen ukazatel funkce.

V příkladu jsou nejprve k dispozici předané deklarace pro a struct pro funkci, která vrací structhodnotu . Kompilátor předpokládá, že struct používá konvenci volání jazyka C++. Dále je struct definice, která ve výchozím nastavení používá konvenci volání jazyka C. Vzhledem k tomu, že kompilátor nezná konvenci volání, dokud nedokončí čtení celého structsouboru , předpokládá se také volání konvence struct návratového structget_c2 typu jazyka C++.

Následuje struct další deklarace funkce, která vrátí structhodnotu . V tuto chvíli kompilátor ví, že structkonvence volání je C++. Podobně je ukazatel funkce, který vrací struct, definován za definicí struct . Kompilátor teď ví, že struct používá konvenci volání jazyka C++.

Pokud chcete vyřešit chyby C2440 způsobené nekompatibilními konvencemi volání, deklarujte funkce, které vrací UDT za definicí 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
}

Přiřazení nuly k vnitřnímu ukazateli

K C2440 může dojít také v případě, že přiřadíte nulu k vnitřní ukazateli:

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

Uživatelem definované převody

C2440 může také dojít k nesprávnému použití uživatelem definovaného převodu. Pokud je například operátor převodu definován jako explicit, kompilátor ho nemůže použít v implicitní převod. Další informace o uživatelsky definovaných převodech naleznete v tématu Převody definované uživatelem (C++/CLI)). Tato ukázka vygeneruje 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 Vytvoření

K C2440 může dojít také v případě, že se pokusíte vytvořit instanci pole v C++/CLI, jehož typ je Array. Další informace naleznete v tématu Pole. Další ukázka vygeneruje 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));
}

Atributy

K C2440 může dojít také kvůli změnám ve funkci atributů. Následující ukázka vygeneruje C2440.

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

Přetypování rozšíření komponent

Kompilátor Jazyka Microsoft C++ již neumožňuje const_cast operátor přetypovat při kompilaci zdrojového kódu pod /clr.

K vyřešení tohoto operátoru C2440 použijte správný operátor přetypování. Další informace naleznete v tématu Operátory přetypování.

Tato ukázka vygeneruje 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
}

Shoda se změnami shody šablon

C2440 může nastat kvůli změnám shody kompilátoru v sadě Visual Studio 2015 Update 3. Dříve kompilátor nesprávně zacházel s určitými jedinečnými výrazy jako se stejným typem při identifikaci shody šablony pro static_cast operaci. Kompilátor teď rozlišuje typy správně a kód, který se spoléhal na předchozí static_cast chování, je poškozený. Chcete-li tento problém vyřešit, změňte argument šablony tak, aby odpovídal typu parametru šablony, nebo použijte reinterpret_cast přetypování ve stylu jazyka C.

Tato ukázka vygeneruje 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);
}

Tato chyba se může zobrazit v kódu ATL, který používá SINK_ENTRY_INFO makro definované v <atlcom.h>.

Inicializace kopírování seznamu

Visual Studio 2017 a novější správně vyvolává chyby kompilátoru související s vytvářením objektů pomocí seznamů inicializátorů. Tyto chyby nebyly zachyceny v sadě Visual Studio 2015 a mohly by vést k chybám nebo nedefinovaným chováním modulu runtime. V jazyce C++17 copy-list-initialization se kompilátor vyžaduje, aby zvážil explicitní constructnebo přetížené řešení, ale pokud je toto přetížení skutečně vybráno, musí vyvolat chybu.

Následující příklad se zkompiluje v sadě Visual Studio 2015, ale ne v sadě 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 &'
}

Pokud chcete chybu opravit, použijte přímou inicializaci:

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

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

kvalifikátory cv ve třídě constructIon

V sadě Visual Studio 2015 kompilátor někdy nesprávně ignoruje kvalifikátor cv při generování objektu třídy prostřednictvím constructnebo volání. Tato chyba může potenciálně způsobit chybové ukončení nebo neočekávané chování modulu runtime. Následující příklad se zkompiluje v sadě Visual Studio 2015, ale vyvolá chybu kompilátoru v sadě Visual Studio 2017 a novější:

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

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

Chcete-li chybu opravit, deklarujte operátor int() jako const.