Derleyici Hatası C2440
'başlatma' : 'type1' öğesinden 'type2' türüne dönüştürülemez
'conversion' : 'type1'den 'type2' türüne dönüştürülemez
Derleyici, 'den *type1*
*type2*
örtük olarak öğesine dönüştüremez veya belirtilen atama veya dönüştürme işlecini kullanamaz.
Açıklamalar
Derleyici, C2440'ı örtük olarak veya belirtilen atama veya dönüştürme işlecini kullanarak bir türden diğerine dönüştüremediğinde oluşturur. Bu hatayı oluşturmanın birçok yolu vardır. Örnekler bölümünde bazı yaygın olanları listeledik.
Örnekler
C++ dize değişmez değerleri şunlardır: const
C2440, derleyici uyumluluğu seçeneği /Zc:strictStrings
ayarlandığında C++ kodunda bir dize değişmez değeri kullanarak ( veya wchar_t*
) olmayanconstchar*
bir başlatma girişiminde bulunursanız kaynaklanabilir. C'de, dize değişmez değerinin türü dizisidir char
, ancak C++'da dizisidir const char
. Bu örnek C2440 oluşturur:
// 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 u8
değişmez değerleri şunlardır: const char8_t
C++20 veya altında/Zc:char8_t
, UTF-8 değişmez karakter veya dizesi (veya gibiu8"String"
u8'a'
) sırasıyla veya const char8_t[N]
türündedirconst char8_t
. Bu örnek, C++17 ile C++20 arasındaki derleyici davranışının nasıl değiştiğini gösterir:
// 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
}
Üye işaretçisi
Bir işaretçiyi üyeye void*
dönüştürmeye çalışırsanız C2440'ı görebilirsiniz. Sonraki örnek C2440 oluşturur:
// 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);
}
};
Tanımlanmamış türün ataması
Yalnızca ileriye doğru bildirilen ancak tanımlanmayan bir türden tür atamayı denerseniz derleyici C2440'ı yayar. Bu örnek C2440 oluşturur:
// 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 *'
}
Uyumsuz çağırma kuralı
Sonraki örneğin 15. ve 16. satırlarındaki C2440 hataları iletiyle nitelenir Incompatible calling conventions for UDT return value
. UDT, sınıf, structveya birleşim gibi kullanıcı tanımlı bir türdür. Bu tür uyumsuzluk hataları, bir iletme bildiriminin dönüş türünde belirtilen bir UDT'nin çağırma kuralı UDT'nin gerçek çağrı kuralıyla çakıldığında ve bir işlev işaretçisi söz konusu olduğunda oluşur.
Örnekte, ilk olarak döndüren structbir struct işlev için ve için iletme bildirimleri vardır. Derleyici, C struct ++ çağırma kuralını kullandığını varsayar. Sonraki tanım, struct varsayılan olarak C çağırma kuralını kullanır. Derleyici, değerinin struct tamamını structokumayı bitirene kadar çağrısı kuralını bilmediğinden, dönüş türündeki için struct çağırma kuralının get_c2
da C++ olduğu varsayılır.
öğesinin struct ardından değerini döndüren başka bir işlev bildirimi gelir struct. Bu noktada, derleyici 'nin çağırma kuralının structC++ olduğunu bilir. Benzer şekilde, işlevini döndüren structişlev işaretçisi tanımdan struct sonra tanımlanır. Derleyici artık C++ çağırma kuralını kullandığını biliyor struct .
Uyumsuz çağrı kurallarının neden olduğu C2440 hatalarını çözmek için, UDT tanımından sonra UDT döndüren işlevleri bildirin.
// 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
}
İç işaretçiye sıfır atama
İç işaretçiye sıfır atarsanız C2440 da oluşabilir:
// 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
}
Kullanıcı tanımlı dönüştürmeler
C2440, kullanıcı tanımlı dönüştürmenin yanlış kullanımı için de oluşabilir. Örneğin, bir dönüştürme işleci olarak explicit
tanımlandığında derleyici bunu örtük bir dönüştürmede kullanamaz. Kullanıcı tanımlı dönüştürmeler hakkında daha fazla bilgi için bkz . Kullanıcı Tanımlı Dönüştürmeler (C++/CLI)). Bu örnek C2440 oluşturur:
// 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
Oluşturma
C++/CLI'da türü Arrayolan bir dizinin örneğini oluşturmaya çalışırsanız da C2440 oluşabilir. Daha fazla bilgi için bkz . Diziler. Sonraki örnek C2440 oluşturur:
// 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));
}
Öznitelikler
C2440, öznitelikler özelliğindeki değişiklikler nedeniyle de oluşabilir. Aşağıdaki örnek C2440 oluşturur.
// c2440f.cpp
// compile with: /LD
[ module(name="PropDemoLib", version=1.0) ]; // C2440
// try the following line instead
// [ module(name="PropDemoLib", version="1.0") ];
Bileşen uzantıları aşağı yayınları
Microsoft C++ derleyicisi, altında kaynak kodu derlerken işlecin artık dökümünü azaltmasına izin vermemeye başladıconst_cast
./clr
Bu C2440 sorununu çözmek için doğru atama işlecini kullanın. Daha fazla bilgi için bkz . Atama işleçleri.
Bu örnek C2440 oluşturur:
// 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
}
Uyumlu şablon eşleşme değişiklikleri
C2440, Visual Studio 2015 Güncelleştirme 3'te derleyicide yapılan uyumluluk değişiklikleri nedeniyle oluşabilir. Daha önce derleyici, bir işlem için bir şablon eşleşmesi tanımlarken belirli ayrı ifadeleri yanlış bir static_cast
şekilde aynı tür olarak değerlendirdi. Artık derleyici türleri doğru bir şekilde ayırt eder ve önceki static_cast
davranışa bağlı olan kod bozulur. Bu sorunu düzeltmek için, şablon bağımsız değişkenini şablon parametre türüyle eşleşecek şekilde değiştirin veya veya C stilinde bir reinterpret_cast
atama kullanın.
Bu örnek C2440 oluşturur:
// 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);
}
Bu hata, içinde tanımlanan makroyu kullanan ATL kodunda SINK_ENTRY_INFO
<atlcom.h>
görünebilir.
Kopya listesi-başlatma
Visual Studio 2017 ve üzeri, başlatıcı listelerini kullanarak nesne oluşturmayla ilgili derleyici hatalarını doğru bir şekilde oluşturur. Bu hatalar Visual Studio 2015'te yakalanmadı ve kilitlenmelere veya tanımlanmamış çalışma zamanı davranışına yol açabilir. C++17 copy-list-initialization içinde derleyicinin açık constructveya aşırı yük çözümlemesi için dikkate alması gerekir, ancak bu aşırı yükleme gerçekten seçilirse hata vermesi gerekir.
Aşağıdaki örnek Visual Studio 2015'te derlenmiş ancak Visual Studio 2017'de derlenmemektedir.
// 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 &'
}
Hatayı düzeltmek için doğrudan başlatmayı kullanın:
// C2440k.cpp
struct A
{
explicit A(int) {}
A(double) {}
};
int main()
{
const A& a2{ 1 };
}
sınıf constructiyonlarında cv-niteleyicileri
Visual Studio 2015'te derleyici bazen bir veya çağrısı aracılığıyla bir sınıf nesnesi oluştururken cv niteleyicisini yanlış bir constructşekilde yoksayar. Bu hata kilitlenmeye veya beklenmeyen çalışma zamanı davranışına neden olabilir. Aşağıdaki örnek, Visual Studio 2015'te derlenmiş ancak Visual Studio 2017 ve sonraki sürümlerde derleyici hatası oluşturur:
struct S
{
S(int);
operator int();
};
int i = (const S)0; // error C2440
Hatayı düzeltmek için int() işlecini olarak constbildirin.
Geri Bildirim
https://aka.ms/ContentUserFeedback.
Çok yakında: 2024 boyunca, içerik için geri bildirim mekanizması olarak GitHub Sorunları’nı kullanımdan kaldıracak ve yeni bir geri bildirim sistemiyle değiştireceğiz. Daha fazla bilgi için bkz.Gönderin ve geri bildirimi görüntüleyin