Mengelakkan Halimunan Ahli Awam dan Pembengkakan Kod dalam Templat Kelas Diwarisi
Pengaturcaraan berorientasikan objek bergantung pada warisan ahli kelas yang dilindungi dan awam. Dalam persekitaran bukan templat, warisan ini adalah mudah. Walau bagaimanapun, apabila memperkenalkan templat kelas, isu asas timbul: ahli awam kelas asas menjadi tidak kelihatan kepada templat kelas terbitan.
Masalahnya
Pertimbangkan contoh berikut :
<code class="cpp">class CBase { public: int Fn1(void) { ... } }; class CDerived : public CBase { public: int FnSum(void) { ... CBase::Fn1(); ... } };</code>
Apabila membuat templat kod ini, ahli Fn1() CBase hilang daripada perspektif CDerived:
<code class="cpp">template<unsigned int BYTES> class CBase { public: int Fn1(void) { ... } }; template<unsigned int BYTES> class CDerived : public CBase<BYTES> { public: int FnSum(void) { ... Fn1(); ... } // Error: Fn1 not found! };</code>
Penyelesaian
Pelbagai penyelesaian wujud untuk menangani isu ini:
Penyelesaian 1 (Awalan Verbose):
<code class="cpp">int FnSum(void) { return CBase<BYTES>::Fn1() + CBase<BYTES>::Fn2() + CBase<BYTES>::Arr[0]; }</code>
Walau bagaimanapun, pendekatan ini memperkenalkan bloat kod yang berlebihan apabila merujuk berbilang ahli.
Penyelesaian 2 (Awalan Verbose "ini->"):
<code class="cpp">int FnSum(void) { return this->Fn1() + this->Fn2() + this->Arr[0]; }</code>
Serupa dengan Penyelesaian 1, tetapi kurang bertutur kata.
Penyelesaian 3 (Menggunakan Pernyataan):
<code class="cpp">using CBase<BYTES>::Arr; using CBase<BYTES>::Fn1; using CBase<BYTES>::Fn2;</code>
Ini membenarkan akses terus kepada ahli CBase tanpa awalan tambahan.
Penyelesaian 4 (Mod Permisif):
<code class="cpp">// Compiler flags: /permissive- (MSVC), -fpermissive (GCC/Cl), -fno-implicit-templates (Clang)</code>
Melumpuhkan pematuhan C yang ketat, menyelesaikan isu tetapi mungkin menimbulkan kebimbangan mudah alih.
Penyelesaian yang Lebih Baik
Sementara Penyelesaian 3 adalah lebih bersih daripada yang lain, ia masih memerlukan pernyataan "menggunakan" berulang. Makro boleh memudahkan perkara ini:
<code class="cpp">#include <boost/preprocessor.hpp> #define USING_ONE(r, base, member) using base::member; #define USING_ALL(base, ...) BOOST_PP_SEQ_FOR_EACH(USING_ONE, base, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)) #define USING_CBASE(param) USING_ALL(CBase<param>, Arr, Fn1, Fn2, Fn3, Fn4, Fn5)</code>
Dalam kelas terbitan:
<code class="cpp">USING_CBASE(BYTES); // Makes all mentioned CBase members directly accessible</code>
Pendekatan ini mengurangkan pembekuan dan penduaan kod dengan ketara.
Atas ialah kandungan terperinci Mengapakah ahli awam kelas asas menjadi tidak kelihatan apabila mewarisi templat kelas, dan apakah penyelesaian kepada masalah ini?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!