Bagikan melalui


Compiler Error C2440

'inisialisasi' : tidak dapat mengonversi dari 'type1' ke 'type2'
'konversi' : tidak dapat mengonversi dari 'type1' ke 'type2'

Pengkompilasi tidak dapat secara implisit mengonversi dari *type1* ke *type2*, atau tidak dapat menggunakan operator cast atau konversi yang ditentukan.

Keterangan

Pengkompilasi menghasilkan C2440 ketika tidak dapat mengonversi dari satu jenis ke jenis lainnya, baik secara implisit atau dengan menggunakan operator pemeran atau konversi yang ditentukan. Ada banyak cara untuk menghasilkan kesalahan ini. Kami telah mencantumkan beberapa yang umum di bagian Contoh.

Contoh

Literal string C++ adalah const

C2440 dapat disebabkan jika Anda mencoba menginisialisasi non-constchar* (atau wchar_t*) dengan menggunakan string literal dalam kode C++, ketika opsi /Zc:strictStrings kesuaian kompilator diatur. Di C, jenis string literal adalah array dari char, tetapi di C++, itu adalah array dari const char. Sampel ini menghasilkan 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 u8 literal adalah const char8_t

Dalam C++20 atau di bawah /Zc:char8_t, karakter atau string harfiah UTF-8 (seperti u8'a' atau u8"String") masing-masing berjenis const char8_t atau const char8_t[N], . Sampel ini menunjukkan bagaimana perilaku pengkompilasi berubah antara C++17 dan 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
}

Penunjuk ke anggota

Anda mungkin melihat C2440 jika Anda mencoba mengonversi pointer ke anggota menjadi void*. Sampel berikutnya menghasilkan 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);
   }
};

Pemeran jenis yang tidak ditentukan

Pengkompilasi memancarkan C2440 jika Anda mencoba untuk mentransmisikan dari jenis yang hanya diteruskan dideklarasikan tetapi tidak ditentukan. Sampel ini menghasilkan 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 *'
}

Konvensi panggilan yang tidak kompatibel

Kesalahan C2440 pada baris 15 dan 16 dari sampel berikutnya memenuhi syarat dengan Incompatible calling conventions for UDT return value pesan. UDT adalah jenis yang ditentukan pengguna, seperti kelas, struct, atau gabungan. Jenis kesalahan ketidakcocokan ini disebabkan ketika konvensi panggilan UDT yang ditentukan dalam jenis pengembalian deklarasi maju bertentangan dengan konvensi panggilan aktual UDT dan ketika penunjuk fungsi terlibat.

Dalam contoh, pertama-tama ada deklarasi penerusan untuk dan struct untuk fungsi yang mengembalikan struct. Pengkompilasi mengasumsikan bahwa struct menggunakan konvensi panggilan C++. Selanjutnya adalah struct definisi, yang menggunakan konvensi panggilan C secara default. Karena pengkompilasi tidak tahu konvensi struct panggilan hingga selesai membaca seluruh struct, konvensi panggilan untuk struct dalam jenis get_c2 pengembalian juga diasumsikan sebagai C++.

struct diikuti oleh deklarasi fungsi lain yang mengembalikan struct. Pada titik ini, pengkompilasi tahu bahwa structkonvensi panggilan adalah C++. Demikian pula, penunjuk fungsi, yang mengembalikan struct, didefinisikan setelah struct definisi. Pengkompilasi sekarang tahu struct penggunaan konvensi panggilan C++.

Untuk mengatasi kesalahan C2440 yang disebabkan oleh konvensi panggilan yang tidak kompatibel, nyatakan fungsi yang mengembalikan UDT setelah definisi 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
}

Tetapkan nol ke penunjuk interior

C2440 juga dapat terjadi jika Anda menetapkan nol ke penunjuk interior:

// 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
}

Konversi yang ditentukan pengguna

C2440 juga dapat terjadi untuk penggunaan konversi yang ditentukan pengguna yang salah. Misalnya, ketika operator konversi telah didefinisikan sebagai explicit, pengkompilasi tidak dapat menggunakannya dalam konversi implisit. Untuk informasi selengkapnya tentang konversi yang ditentukan pengguna, lihat Konversi yang Ditentukan Pengguna (C++/CLI)). Sampel ini menghasilkan 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 Penciptaan

C2440 juga dapat terjadi jika Anda mencoba membuat instans array di C++/CLI yang jenisnya adalah Array. Untuk informasi selengkapnya, lihat Array. Sampel berikutnya menghasilkan 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));
}

Atribut

C2440 juga dapat terjadi karena perubahan fitur atribut. Sampel berikut menghasilkan C2440.

// c2440f.cpp
// compile with: /LD
[ module(name="PropDemoLib", version=1.0) ];   // C2440
// try the following line instead
// [ module(name="PropDemoLib", version="1.0") ];

Ekstensi komponen menurunkan transmisi

Pengkompilasi Microsoft C++ tidak lagi memungkinkan const_cast operator untuk menurunkan transmisi saat Anda mengkompilasi kode sumber di bawah /clr.

Untuk mengatasi C2440 ini, gunakan operator cast yang benar. Untuk informasi selengkapnya, lihat Operator casting.

Sampel ini menghasilkan 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
}

Menyesuaikan perubahan kecocokan templat

C2440 dapat terjadi karena perubahan kesuaian pada pengkompilasi di Visual Studio 2015 Update 3. Sebelumnya, pengkompilasi salah memperlakukan ekspresi tertentu yang berbeda sebagai jenis yang sama saat mengidentifikasi kecocokan templat untuk static_cast operasi. Sekarang pengkompilasi membedakan jenis dengan benar, dan kode yang bergantung pada perilaku sebelumnya static_cast rusak. Untuk memperbaiki masalah ini, ubah argumen templat agar sesuai dengan jenis parameter templat, atau gunakan reinterpret_cast cast gaya C atau .

Sampel ini menghasilkan 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);
}

Kesalahan ini dapat muncul dalam kode ATL yang menggunakan makro yang SINK_ENTRY_INFO ditentukan dalam <atlcom.h>.

Salin-daftar-inisialisasi

Visual Studio 2017 dan yang lebih baru meningkatkan kesalahan pengkompilasi dengan benar yang terkait dengan pembuatan objek menggunakan daftar inisialisasi. Kesalahan ini tidak tertangkap di Visual Studio 2015 dan dapat menyebabkan crash atau perilaku runtime yang tidak ditentukan. Dalam copy-list-initialization C++17, pengkompilasi diperlukan untuk mempertimbangkan resolusi eksplisit constructatau untuk kelebihan beban, tetapi harus menimbulkan kesalahan jika kelebihan beban tersebut benar-benar dipilih.

Contoh berikut mengkompilasi di Visual Studio 2015 tetapi tidak di 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 &'
}

Untuk memperbaiki kesalahan, gunakan inisialisasi langsung:

// C2440k.cpp
struct A
{
    explicit A(int) {}
    A(double) {}
};

int main()
{
    const A& a2{ 1 };
}

cv-qualifiers di kelas construction

Di Visual Studio 2015, pengkompilasi terkadang salah mengabaikan kualifikasi cv saat membuat objek kelas melalui constructpanggilan atau . Cacat ini berpotensi menyebabkan crash atau perilaku runtime tak terduga. Contoh berikut mengkompilasi di Visual Studio 2015 tetapi menimbulkan kesalahan pengkompilasi di Visual Studio 2017 dan yang lebih baru:

struct S
{
    S(int);
    operator int();
};

int i = (const S)0; // error C2440

Untuk memperbaiki kesalahan, nyatakan operator int() sebagai const.