Not
Åtkomst till denna sida kräver auktorisation. Du kan prova att logga in eller byta katalog.
Åtkomst till denna sida kräver auktorisation. Du kan prova att byta katalog.
"initializing" : kan inte konvertera från 'type1' till 'type2'
"konvertering" : kan inte konvertera från "type1" till "type2"
Anmärkningar
Kompilatorn kan inte implicit konvertera från type1 till type2eller kan inte använda den angivna cast- eller konverteringsoperatorn.
Kompilatorn genererar C2440 när den inte kan konvertera från en typ till en annan, antingen implicit eller med hjälp av den angivna cast- eller konverteringsoperatorn. Det finns många sätt att generera det här felet. Vi har listat några vanliga i avsnittet Exempel.
Exempel
C++-strängliteraler är const
C2440 kan orsakas om du försöker initiera en icke-constchar* (eller wchar_t*) med hjälp av en strängliteral i C++-kod när kompilatorkonformitetsalternativet /Zc:strictStrings har angetts. I C är typen av en strängliteral matris av char, men i C++ är det matris av const char. Det här exemplet genererar 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
}
C++20-literaler u8 är const char8_t
I C++20 eller under /Zc:char8_tär ett UTF-8-literaltecken eller sträng (till exempel u8'a' eller u8"String") av typen const char8_t eller const char8_t[N]. Det här exemplet visar hur kompilatorbeteendet ändras mellan C++17 och 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
}
Pekare till medlem
Du kan se C2440 om du försöker konvertera en pekare till medlem till void*. Nästa exempel genererar 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);
}
};
Gjutning av odefinierad typ
Kompilatorn genererar C2440 om du försöker konvertera från en typ som endast är förklarad i förväg men inte definierad. Det här exemplet genererar 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 *'
}
Inkompatibel samtalskonvention
C2440-felen på raderna 15 och 16 i nästa exempel är kvalificerade med meddelandet Incompatible calling conventions for UDT return value . En UDT är en användardefinierad typ, till exempel en klass, structeller union. Den här typen av inkompatibilitetsfel orsakas när anropskonventionen för en UDT som anges i returtypen för en framåtdeklaration står i konflikt med UDT:s faktiska anropskonvention och när en funktionspekare ingår.
I exemplet finns det först framåtdeklarationer för en struct och för en funktion som returnerar struct. Kompilatorn förutsätter att struct använder C++-anropskonventionen. Nästa är struct definitionen, som använder C-anropskonventionen som standard. Eftersom kompilatorn inte känner till anropskonventionen struct förrän den har läst klart hela structantas anropskonventionen för struct i returtypen get_c2 också vara C++.
struct Följs av en annan funktionsdeklaration som returnerar struct. Nu vet kompilatorn att structanropskonventionen är C++. På samma sätt definieras funktionspekaren, som returnerar struct, efter struct definitionen. Kompilatorn känner nu till struct användningskonventionen för C++-anrop.
För att lösa C2440-fel som orsakas av inkompatibla anropskonventioner deklarerar du funktioner som returnerar en UDT efter UDT-definitionen.
// 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
}
Tilldela noll till inre pekare
C2440 kan också inträffa om du tilldelar noll till en inre pekare:
// 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
}
Användardefinierade konverteringar
C2440 kan också inträffa vid felaktig användning av en användardefinierad konvertering. När en konverteringsoperator till exempel har definierats som explicitkan kompilatorn inte använda den i en implicit konvertering. Mer information om användardefinierade konverteringar finns iUser-Defined Konverteringar (C++/CLI)). Det här exemplet genererar 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 skapelse
C2440 kan också inträffa om du försöker skapa en instans av en matris i C++/CLI vars typ är en Array. Mer information finns i Matriser. Nästa exempel genererar 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));
}
Egenskaper
C2440 kan också inträffa på grund av ändringar i attributfunktionen. I följande exempel genereras C2440.
// c2440f.cpp
// compile with: /LD
[ module(name="PropDemoLib", version=1.0) ]; // C2440
// try the following line instead
// [ module(name="PropDemoLib", version="1.0") ];
Komponenttillägg nedtypekonverteringar
Microsoft C++-kompilatorn tillåter inte längre att operatornconst_cast gör en downcast när du kompilerar källkoden under /clr.
Lös denna C2440 genom att använda rätt gjutningsoperator. För mer information, se Castingoperatorer.
Det här exemplet genererar 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
}
Ändringar för att anpassa mallmatchning
C2440 kan inträffa på grund av överensstämmelseändringar i kompilatorn i Visual Studio 2015 Update 3. Tidigare behandlade kompilatorn felaktigt vissa distinkta uttryck som samma typ när en mallmatchning identifierades för en static_cast åtgärd. Nu särskiljer kompilatorn typerna korrekt och koden som förlitade sig på det tidigare static_cast beteendet är bruten. Åtgärda problemet genom att ändra mallargumentet så att det matchar mallparametertypen, eller använda en reinterpret_cast eller C-formatering.
Det här exemplet genererar 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);
}
Det här felet kan visas i ATL-kod som använder makrot SINK_ENTRY_INFO som definierats i <atlcom.h>.
Kopieringsbaserad listinitiering
Visual Studio 2017 och senare skapar kompilatorfel som är relaterade till att skapa objekt med hjälp av initialiserarlistor. Dessa fel fångades inte i Visual Studio 2015 och kan leda till krascher eller odefinierat körningsbeteende. I C++17 copy-list-initialization måste kompilatorn beakta en explicit konstruktor vid överbelastningslösning, men den måste generera ett fel om den överbelastningen verkligen väljs.
Följande exempel kompileras i Visual Studio 2015 men inte i 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 &'
}
Du kan åtgärda felet genom att använda direktinitiering:
// C2440k.cpp
struct A
{
explicit A(int) {}
A(double) {}
};
int main()
{
const A& a2{ 1 };
}
cv-kvalificerare i klasskonstruktion
I Visual Studio 2015 ignorerar kompilatorn ibland felaktigt cv-qualifier när ett klassobjekt genereras via ett konstruktoranrop. Den här defekten kan potentiellt orsaka en krasch eller oväntat körningsbeteende. Följande exempel kompileras i Visual Studio 2015 men skapar ett kompilatorfel i Visual Studio 2017 och senare:
struct S
{
S(int);
operator int();
};
int i = (const S)0; // error C2440
Om du vill korrigera felet deklarerar du operatorn int() som const.