Rumah >pembangunan bahagian belakang >C++ >Mengapakah Permulaan Ahli Statik dalam Kelas Templat Berkelakuan Berbeza?

Mengapakah Permulaan Ahli Statik dalam Kelas Templat Berkelakuan Berbeza?

DDD
DDDasal
2024-10-28 08:57:02732semak imbas

 Why Does Static Member Initialization in Templated Classes Behave Differently?

Komplikasi Permulaan Ahli Statik dalam Kelas Templat

Pengamatan ahli statik dalam C ialah teknik yang digunakan secara meluas, tetapi ia boleh menjadi rumit apabila berurusan dengan kelas templat. Dalam kelas bukan templat, struct helper bersarang boleh digunakan untuk pemula, tetapi pendekatan ini gagal apabila kelas yang disertakan ditemplat.

Pertimbangkan contoh mudah berikut:

<code class="cpp">struct A
{
    static std::string mA;
    static InitHelper mInit;

    static const std::string& getA() { return mA; }
};
std::string A::mA;
A::InitHelper A::mInit;


template<class T>
struct B
{
    static std::string mB;
    static InitHelper mInit;

    static const std::string& getB() { return mB; }
    static InitHelper& getHelper() { return mInit; }
};
template<class T>
std::string B<T>::mB;
template<class T>
typename B<T>::InitHelper B<T>::mInit;

int main()
{
    std::cout << "A = " << A::getA() << std::endl;

    // Comment/uncomment lines to observe different behaviors
    // std::cout << "B = " << B<int>::getB() << std::endl; // [1]
    // B<int>::getHelper(); // [2]
}</code>

Gelagat Jangkaan:

Apabila [1] tidak diulas dan [2] diulas, kami menjangkakan B::mB akan dimulakan kepada "Helo, saya B." . Walau bagaimanapun, ini tidak berlaku.

Gelagat Sebenar:

  • Dengan [1] dan [2] mengulas: Tiada kesan sampingan berlaku.
  • Dengan [1] tidak diulas: B::getB() mengembalikan rentetan kosong.
  • Dengan [1] dan [2 ] tidak diulas: B::mB dimulakan dengan betul.
  • Dengan [1] diulas dan [2] tidak diulas: Ralat pembahagian berlaku semasa pengamulaan statik.

Sebab Percanggahan:

Menurut piawaian ISO/IEC C 2003, ahli templat diwujudkan secara tersirat apabila dirujuk dalam konteks yang memerlukan takrifannya untuk wujud. Walau bagaimanapun, permulaan ahli data statik (dan sebarang kesan sampingan yang berkaitan) hanya berlaku apabila ahli data statik digunakan secara eksplisit. Ini bermakna jika ahli templat hanya dirujuk dalam templat yang tidak segera atau dalam konteks lain yang tidak memerlukan instantiasi penuhnya, ahli data statiknya tidak akan dimulakan.

Dalam contoh, B:: getB() memerlukan B::mB wujud, tetapi ini hanya memaksa instantiasi perisytiharan templat ahli, bukan takrifnya (termasuk pemula). Sebaliknya, B::getHelper() memerlukan takrifan B::mInit kerana ia mengembalikan rujukan kepadanya.

Penyelesaian:

Piawaian melarang bahawa takrif ahli data statik templat kelas khusus secara eksplisit telah memerintahkan pemulaan, manakala ahli data statik templat kelas lain mempunyai pemulaan tidak tertib. Untuk memastikan susunan permulaan yang konsisten, seseorang mesti menggunakan pengkhususan eksplisit.

Atas ialah kandungan terperinci Mengapakah Permulaan Ahli Statik dalam Kelas Templat Berkelakuan Berbeza?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
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