Aracılığıyla paylaş


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 explicittanı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.