Compilerfehler C2440
'Initialisierung': Kann nicht von 'type1' in 'type2' konvertiert werden.
'konvertierung': kann nicht von 'type1' in 'type2' konvertiert werden.
Der Compiler kann nicht implizit in *type1*
*type2*
oder nicht den angegebenen Umwandlungs- oder Konvertierungsoperator verwenden.
Hinweise
Der Compiler generiert C2440, wenn er nicht von einem Typ in einen anderen konvertiert werden kann, entweder implizit oder mithilfe des angegebenen Umwandlungs- oder Konvertierungsoperators. Es gibt viele Möglichkeiten, diesen Fehler zu generieren. Im Abschnitt "Beispiele" sind einige häufig verwendete aufgeführt.
Beispiele
C++-Zeichenfolgenliterale sind const
C2440 kann verursacht werden, wenn Sie versuchen, ein Nicht-constchar*
(oder wchar_t*
) mit einem Zeichenfolgenliteral im C++-Code zu initialisieren, wenn die Compilerkonformitätsoption /Zc:strictStrings
festgelegt ist. In C ist der Typ eines Zeichenfolgenliterals array von char
, aber in C++ ist es Array von const char
. Dieses Beispiel generiert 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-Literale u8
sind const char8_t
In C++20 oder unter /Zc:char8_t
, ist ein UTF-8-Literalzeichen oder eine Zeichenfolge (zu8'a'
. B. oder u8"String"
) vom Typ bzw. vom Typ const char8_t
.const char8_t[N]
In diesem Beispiel wird gezeigt, wie sich das Compilerverhalten zwischen C++17 und C++20 ändert:
// 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
}
Zeiger auf Member
Möglicherweise wird C2440 angezeigt, wenn Sie versuchen, einen Zeiger in ein Element void*
zu konvertieren. Im nächsten Beispiel wird C2440 generiert:
// 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);
}
};
Umwandlung des nicht definierten Typs
Der Compiler gibt C2440 aus, wenn Sie versuchen, einen Vorwärtstyp zu umwandeln, der nur deklariert, aber nicht definiert ist. Dieses Beispiel generiert 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 *'
}
Inkompatible Anrufkonvention
Die C2440-Fehler in den Zeilen 15 und 16 des folgenden Beispielcodes sind durch die Meldung Incompatible calling conventions for UDT return value
gekennzeichnet. Ein UDT ist ein benutzerdefinierter Typ, z. B. eine Klasse oder structeine Union. Derartige Inkompatibilitätsfehler treten auf, wenn die Aufrufkonvention eines UDTs, die im Rückgabetyp einer Vorwärtsdeklaration festgelegt wurde, Konflikte mit der aktuellen Aufrufkonvention des UDTs verursacht und zugleich ein Funktionszeiger betroffen ist.
Im Beispiel gibt es zuerst Weiterleitungsdeklarationen für eine struct und für eine Funktion, die die struct. Der Compiler geht davon aus, dass die struct C++-Aufrufkonvention verwendet wird. Als Nächstes ist die struct Definition, die standardmäßig die C-Aufrufkonvention verwendet. Da der Compiler die Aufrufkonvention der struct gesamten structLeserichtung nicht kennt, wird die Aufrufkonvention für den struct Rückgabetyp get_c2
auch als C++ angenommen.
Gefolgt struct von einer weiteren Funktionsdeklaration, die die struct. An diesem Punkt weiß der Compiler, dass die structAufrufenskonvention C++ ist. Entsprechend wird der Funktionszeiger, der den structWert zurückgibt, nach der struct Definition definiert. Der Compiler kennt jetzt die struct C++-Aufrufkonvention.
Um C2440-Fehler zu beheben, die durch inkompatible Aufrufkonventionen verursacht werden, deklarieren Sie Funktionen, die nach der UDT-Definition ein UDT zurückgeben.
// 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
}
Zuweisen von Null zum Innenzeiger
C2440 kann auch auftreten, wenn Sie einem inneren Zeiger 0 (null) zuweisen:
// 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
}
Benutzerdefinierte Konvertierungen
C2440 kann auch bei nicht ordnungsgemäßer Verwendung einer benutzerdefinierten Konvertierung auftreten. Wenn beispielsweise ein Konvertierungsoperator definiert explicit
wurde, kann der Compiler ihn nicht in einer impliziten Konvertierung verwenden. Weitere Informationen zu benutzerdefinierten Konvertierungen finden Sie unter User-Defined Conversions (C++/CLI).For more information about user-defined conversions, see User-Defined Conversions (C++/CLI)). Dieses Beispiel generiert 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
Kreation
C2440 kann auch auftreten, wenn Sie versuchen, eine Instanz eines Arrays in C++/CLI zu erstellen, dessen Typ ein Arrayist. Weitere Informationen finden Sie unter Arrays. Im nächsten Beispiel wird C2440 generiert:
// 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));
}
Attribute
C2440 kann auch aufgrund von Änderungen in der Attributfunktion auftreten. Im folgenden Beispiel wird C2440 generiert.
// c2440f.cpp
// compile with: /LD
[ module(name="PropDemoLib", version=1.0) ]; // C2440
// try the following line instead
// [ module(name="PropDemoLib", version="1.0") ];
Komponentenerweiterungen nach unten umwandeln
Der Microsoft C++-Compiler lässt den const_cast
Operator beim Kompilieren des Quellcodes unter /clr
nicht mehr herunter.
Um den Fehler C2440 zu beheben, verwenden Sie den richtigen Umwandlungsoperator. Weitere Informationen finden Sie unter Umwandlungsoperatoren.
Dieses Beispiel generiert 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
}
Übereinstimmende Vorlagenänderungen
C2440 kann aufgrund von Konformitätsänderungen am Compiler in Visual Studio 2015 Update 3 auftreten. Zuvor behandelte der Compiler bestimmte unterschiedliche Ausdrücke falsch als denselben Typ, wenn eine Vorlagenausstimmung für einen static_cast
Vorgang identifiziert wird. Nun unterscheidet der Compiler die Typen richtig, und Code, der auf dem vorherigen static_cast
Verhalten basiert, ist fehlerhaft. Um dieses Problem zu beheben, ändern Sie das Vorlagenargument so, dass es dem Vorlagenparametertyp entspricht, oder verwenden Sie eine reinterpret_cast
Umwandlung im C-Stil.
Dieses Beispiel generiert 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);
}
Dieser Fehler kann im ATL-Code angezeigt werden, der das SINK_ENTRY_INFO
in <atlcom.h>
.
copy-list-Initialisierung
Visual Studio 2017 und höher lösen Compilerfehler im Zusammenhang mit der Objekterstellung mithilfe von Initialisierungslisten ordnungsgemäß aus. Diese Fehler wurden in Visual Studio 2015 nicht erfasst und konnten zu Abstürzen oder nicht definierten Laufzeitverhalten führen. In der C++17-Copy-List-Initialisierung muss der Compiler einen expliziten Konstruktor für die Überladungsauflösung in Betracht ziehen, aber einen Fehler auslösen, wenn diese Überladung tatsächlich ausgewählt wird.
Im folgenden Beispiel wird in Visual Studio 2015 kompiliert, aber nicht 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 &'
}
Verwenden Sie direkte Initialisierung, um den Fehler zu korrigieren:
// C2440k.cpp
struct A
{
explicit A(int) {}
A(double) {}
};
int main()
{
const A& a2{ 1 };
}
CV-Qualifizierer in der Klassenkonstruktion
In Visual Studio 2015 ignoriert der Compiler beim Generieren eines Klassenobjekts über einen Konstruktoraufruf manchmal fälschlicherweise die CV-Qualifizierer. Dieser Fehler kann möglicherweise zu einem Absturz oder unerwartetem Laufzeitverhalten führen. Das folgende Beispiel kompiliert in Visual Studio 2015, löst jedoch einen Compilerfehler in Visual Studio 2017 und höher aus:
struct S
{
S(int);
operator int();
};
int i = (const S)0; // error C2440
Um den Fehler zu beheben, deklarieren Sie den Operator int() als const.