Ralat kompilasi C++: Tidak boleh memanggil fungsi ahli ditukar daripada jenis yang tidak menentu, bagaimana untuk menanganinya?

PHPz
Lepaskan: 2023-08-21 21:28:55
asal
960 orang telah melayarinya

C++ ialah bahasa yang ditaip kuat yang mengehadkan penukaran jenis pembolehubah Walau bagaimanapun, dalam beberapa kes, kami mungkin perlu melakukan penukaran jenis pada objek jenis yang tidak menentu, terutamanya dalam pembangunan terbenam, kami selalunya perlu mengakses daftar perkakasan biasanya jenis yang tidak menentu. Walau bagaimanapun, kerana objek jenis tidak menentu mempunyai semantik khas, pengkompil C++ akan mengenakan beberapa sekatan khas ke atasnya, yang membawa kepada ralat "Tidak boleh memanggil fungsi ahli ditukar daripada jenis yang tidak menentu". Artikel ini akan menerangkan punca ralat ini dan cara menanganinya.

Pertama, mari kita lihat semantik jenis yang tidak menentu. Dalam C++, peranan kata kunci yang tidak menentu adalah untuk memberitahu pengkompil bahawa nilai pembolehubah ini boleh diubah suai di luar program, jadi pengkompil tidak boleh mengoptimumkannya dan mesti memastikan bahawa nilainya dibaca semula setiap kali ia diakses. Khususnya, objek yang tidak menentu mempunyai ciri-ciri berikut:

  • Nilai objek yang tidak menentu boleh diubah suai di luar program, seperti gangguan perkakasan, pelbagai benang, dsb.
  • Setiap kali objek yang tidak menentu diakses, nilainya mesti dibaca semula, dan nilai cache dalam daftar tidak boleh digunakan secara langsung.
  • Akses kepada objek yang tidak menentu tidak boleh disusun semula atau dioptimumkan dan mesti dilakukan mengikut susunan dalam program.

Di bawah semantik ini, kita boleh menggunakan objek jenis meruap untuk mewakili daftar perkakasan Perlu diingat bahawa objek jenis meruap tidak boleh ditukar kepada dan daripada objek jenis tidak meruap, kerana ini akan memusnahkan semantik khasnya. Sebagai contoh, kod berikut adalah salah:

int x = 0;
volatile int &y = x;   // 复制x的地址,但y是volatile类型

x = 1;  // OK,修改x的值
y = 2;  // OK,修改x的值,但要重新读取其值
int z = y;  // 错误,不能读取volatile对象的值
int &u = y;  // 错误,不能将volatile类型的引用转换为非volatile类型
Salin selepas log masuk

Dalam kod di atas, kami cuba menukar pembolehubah tidak meruap x kepada rujukan meruap y, iaitu salah. Walaupun dengan melakukan ini, kita boleh mengubah suai nilai x melalui y dan membaca semula nilainya dengan setiap pengubahsuaian, kita tidak boleh membaca nilai y seperti integer biasa kerana ini akan melanggar semantik jenis yang tidak menentu.

Melangkah lebih jauh, mari kita pertimbangkan situasi yang lebih kompleks, iaitu memanggil fungsi ahli pada objek jenis yang tidak menentu. Sebagai contoh, kita boleh mengisytiharkan fungsi ahli objek sebagai jenis yang tidak menentu, supaya keterlihatan pembolehubah ahlinya boleh dijamin apabila ia dipanggil. Walau bagaimanapun, pengkompil C++ tidak membenarkan penukaran daripada jenis tidak menentu kepada jenis tidak menentu, jadi ralat penyusunan "Tidak boleh memanggil fungsi ahli ditukar daripada jenis meruap" akan berlaku. Contohnya:

class MyClass {
public:
    volatile int x;
    volatile void func() { x = x + 1; }
};

int main() {
    MyClass obj;
    obj.func();  // 错误,不能从volatile类型转换为非volatile类型
    return 0;
}
Salin selepas log masuk

Dalam kod di atas, kami mentakrifkan kelas MyClass, di mana x ialah integer jenis meruap dan func() ialah fungsi ahli jenis meruap, yang bermaksud untuk melaksanakan operasi kenaikan automatik pada x. Dalam fungsi main(), kami mencipta obj objek MyClass dan cuba memanggil fungsi ahlinya func(). Walau bagaimanapun, ini akan menyebabkan ralat kompilasi "Tidak boleh memanggil fungsi ahli ditukar daripada jenis yang tidak menentu". Ini kerana, dalam C++, fungsi ahli dianggap sebagai fungsi biasa dengan parameter penunjuk ini tersembunyi, jadi apabila memanggil fungsi ahli, menukar penunjuk ini daripada jenis tidak meruap kepada jenis tidak menentu adalah tidak dibenarkan.

Jadi, bagaimana kita harus menangani ralat kompilasi ini? Terdapat dua cara untuk menyelesaikan masalah ini. Kaedah pertama adalah untuk mengisytiharkan parameter fungsi ahli sebagai jenis yang tidak menentu supaya pengkompil tidak akan melaporkan ralat. Sebagai contoh:

class MyClass {
public:
    volatile int x;
    void func(volatile MyClass *thisptr) { thisptr->x = thisptr->x + 1; }
};

int main() {
    MyClass obj;
    obj.func(&obj);  // OK,将this指针转换为volatile类型
    return 0;
}
Salin selepas log masuk

Dalam kod di atas, kami mengisytiharkan parameter thisptr fungsi func() sebagai penunjuk MyClass jenis meruap, supaya apabila memanggilnya, penunjuk ini boleh ditukar daripada jenis tidak meruap kepada jenis yang tidak menentu. Walaupun pendekatan ini boleh menyelesaikan masalah, ia menjadikan kod itu bertele-tele dan tidak begitu biasa digunakan.

Kaedah kedua ialah menggunakan teknologi pemadaman jenis untuk menukar penunjuk fungsi ahli ini kepada penunjuk kosong, supaya sekatan pengkompil pada jenis yang tidak menentu boleh dipintas. Contohnya:

class MyClass {
public:
    volatile int x;
    void func() {
        volatile void *vthis = static_cast<volatile void *>(this);
        volatile MyClass *vptr = static_cast<volatile MyClass *>(vthis);
        vptr->x = vptr->x + 1;
    }
};

int main() {
    MyClass obj;
    obj.func();  // OK,使用类型擦除将this指针转换为volatile类型
    return 0;
}
Salin selepas log masuk

Dalam kod di atas, kami menggunakan static_cast untuk menukar penuding ini kepada penuding kosong dahulu, dan kemudian kepada penuding MyClass yang tidak menentu, supaya kita boleh mendapatkan penunjuk ini yang tidak menentu. Walaupun pendekatan ini boleh menyelesaikan masalah, ia memerlukan pemahaman cara menggunakan teknik pemadaman jenis dan boleh menjejaskan kebolehbacaan dan kebolehselenggaraan kod.

Ringkasnya, ralat kompilasi C++ "Tidak boleh memanggil fungsi ahli ditukar daripada jenis yang tidak menentu" disebabkan oleh sekatan khas pengkompil pada jenis yang tidak menentu. Untuk menyelesaikan ralat kompilasi ini, kita boleh mengisytiharkan parameter fungsi ahli sebagai jenis yang tidak menentu, atau menggunakan teknologi pemadaman jenis untuk menukar penunjuk fungsi ahli ini kepada penunjuk lompang. Tidak kira kaedah mana yang digunakan, anda perlu memberi perhatian kepada semantik jenis yang tidak menentu untuk mengelakkan menukar objek yang tidak menentu kepada objek yang tidak menentu dan sebaliknya, yang mungkin membawa kepada keputusan yang salah.

Atas ialah kandungan terperinci Ralat kompilasi C++: Tidak boleh memanggil fungsi ahli ditukar daripada jenis yang tidak menentu, bagaimana untuk menanganinya?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Label berkaitan:
sumber:php.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan