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 char
pole , 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_t
je 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 struct get_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 je kompilátor nutný k zvážení explicitního konstruktoru pro řešení přetížení, ale musí vyvolat chybu, pokud je toto přetížení skutečně vybráno.
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 };
}
cv-kvalifikátory ve konstrukci třídy
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 volání konstruktoru. 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.