Kekaburan dalam Menyahkambiguasi Berbilang Warisan
Apabila berurusan dengan berbilang warisan menggunakan kelas asas templat, kemungkinan isu timbul mengenai penyelesaian fungsi ahli yang tidak jelas. Pertimbangkan senario berikut:
<code class="cpp">template <typename ... Types> class Base { public: template <typename T> typename std::enable_if<Contains<T, Types ...>::value>::type foo() { std::cout << "Base::foo()\n"; } };
Di sini, fungsi foo() hanya boleh dipanggil apabila parameter templat sepadan dengan salah satu jenis dalam pek Jenis. Sekarang, jika kelas terbitan mewarisi daripada berbilang kelas asas dengan set jenis tidak bertindih, pengkompil mungkin menghadapi kesamaran semasa menyelesaikan panggilan foo().
<code class="cpp">struct Derived: public Base<int, char>, public Base<double, void> {};</code>
Dalam kes ini, panggilan Derived(). foo
Mengapa Pengkompil Tidak Dapat Menyelesaikan Kekaburan
Ralat kompilasi timbul kerana peraturan gabungan untuk carian fungsi ahli. Mengikut piawaian C, jika fungsi ahli tidak diisytiharkan dalam kelas terbitan itu sendiri, proses carian mencari kelas asas secara bergilir-gilir. Walau bagaimanapun, jika set pengisytiharan dalam kelas asas berbeza, cantuman menjadi samar-samar.
Dalam senario yang diberikan, kelas terbitan Derived tidak mengisytiharkan foo() secara eksplisit, jadi pengkompil mesti menggabungkan set carian daripada dua kelas asas. Memandangkan kelas asas mengandungi set pengisytiharan yang berbeza untuk foo(), gabungan menghasilkan kesamaran.
Penyelesaian
Untuk menyelesaikan kekaburan ini, satu pilihan ialah menggunakan menggunakan pengisytiharan dalam kelas terbitan untuk mengimport secara eksplisit fungsi ahli yang dikehendaki. Walau bagaimanapun, ini memerlukan pengguna untuk menambah pengisytiharan ini, yang boleh menjadi kata-kata dan tidak praktikal untuk senarai jenis besar.
<code class="cpp">struct Derived: public Base<int, char>, public Base<double, void> { using Base<int, char>::foo; using Base<double, void>::foo; };</code>
Sebagai alternatif, seseorang boleh menggunakan kelas pembantu yang mengumpul dan menggabungkan fungsi ahli daripada semua kelas asas , membenarkan kelas terbitan mengaksesnya secara langsung.
<code class="cpp">template <typename... Bases> struct BaseCollector : Bases... { using Bases::foo...; }; struct Derived : BaseCollector<Base<int, char>, Base<double, void>> {};</code>
Dengan pendekatan ini, pengguna tidak perlu menambah sebarang pengisytiharan tambahan untuk menyelesaikan kekaburan. Kelas BaseCollector menggabungkan set pengisytiharan daripada semua kelas asas dengan berkesan, menjadikan fungsi foo() tersedia kepada kelas terbitan tanpa kesamaran.
Atas ialah kandungan terperinci ## Mengapa Pewarisan Berbilang dengan Kelas Asas Templat Menyebabkan Kekaburan dalam Penyelesaian Fungsi Ahli?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!