Cara Memaksa Permulaan Ahli Statik
Tingkah laku yang sering diabaikan dalam C ialah ahli statik tidak dijamin untuk dimulakan secara automatik. Seseorang mungkin menjangkakan bahawa ahli itu dimulakan dengan instantiasi pertama kelas konkrit. Walau bagaimanapun, seperti yang dicadangkan oleh petikan standard, ini berlaku hanya apabila ahli statik digunakan secara aktif:
"* khususnya, permulaan (dan sebarang kesan sampingan yang berkaitan) bagi ahli data statik tidak berlaku melainkan ahli data statik itu sendiri digunakan dalam cara yang memerlukan takrifan ahli data statik untuk wujud."
Masalahnya
Pertimbangkan kod berikut:
<code class="cpp">template <class D> char register_() { return D::get_dummy(); // static function } template <class D> struct Foo { static char const dummy; }; template <class D> char const Foo<D>::dummy = register_<D>(); // static member initialized with `register_<D>()` struct Bar : Foo<Bar> { static char const get_dummy() { return 42; } };</code>
Secara intuitif, seseorang mungkin menjangkakan dummy akan dimulakan selepas instantiasi Bar. Walau bagaimanapun, ini tidak berlaku.
Persoalannya
Bagaimanakah seseorang boleh memaksa pemulaan dummy tanpa memerlukan instance Bar atau Foo? Selain itu, penyelesaian itu tidak sepatutnya memerlukan rujukan eksplisit ahli oleh pengguna Foo.
Penyelesaian Berpotensi
Penyelesaian 1 (Kesan Minimum pada Kelas Terbitan)
Pengubahsuaian berikut kepada kaedah get_dummy() Bar akan memaksa pemulaan dummy:
<code class="cpp">static char const get_dummy() { (void)dummy; return 42; }</code>
Penyelesaian 2 (Tiada Pengubahsuaian kepada Kelas Terbitan)
Penyelesaian ini menggunakan metaprogramming templat:
<code class="cpp">template<typename T, T> struct value { }; template<typename T> struct HasStatics { static int a; // we force this to be initialized typedef value<int&, a> value_user; }; template<typename T> int HasStatics<T>::a = /* whatever side-effect you want */ 0;</code>
Atau, ia boleh dilakukan tanpa memperkenalkan mana-mana ahli tambahan:
<code class="cpp">template<typename T, T> struct var { enum { value }; }; template<typename T> struct HasStatics { static int a; // we force this to be initialized static int b; // and this char user :var<int&, a>::value, :var<int&, b>::value; }; template<typename T> int HasStatics<T>::a = /* whatever side-effect you want */ 0; template<typename T> int HasStatics<T>::b = /* whatever side-effect you want */ 0;</code>
Atas ialah kandungan terperinci Bagaimana Memaksa Permulaan Ahli Statik dalam C Tanpa Rujukan Eksplisit?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!