Mengapa saya tidak dapat menginisialisasi static
anggota data di kelas?
Standar C ++ hanya mengizinkan jenis integral konstanta statis atau enumerasi untuk diinisialisasi di dalam kelas. Inilah alasannya a
diizinkan untuk diinisialisasi sementara yang lain tidak.
Referensi:
C ++ 03 9.4.2 Anggota data statis
§4
Jika anggota data statis adalah dari integral konst atau jenis enumerasi konst, deklarasinya dalam definisi kelas dapat menentukan penginisialisasi konstan yang akan menjadi ekspresi konstanta integral (5.19). Dalam hal ini, anggota dapat muncul dalam ekspresi konstanta integral. Anggota masih harus ditentukan dalam ruang lingkup namespace jika digunakan dalam program dan definisi ruang lingkup namespace tidak boleh berisi penginisialisasi.
Apa tipe integral?
C ++ 03 3.9.1 Tipe dasar
§7
Tipe bool, char, wchar_t, dan tipe integer bertanda tangan dan tak bertanda tangan secara kolektif disebut tipe integral.43) Sinonim dari tipe integral adalah tipe integer.
Catatan kaki:
43) Oleh karena itu, pencacahan (7.2) tidak terpisahkan; namun, enumerasi dapat dipromosikan menjadi int, unsigned int, long, atau unsigned long, seperti ditentukan dalam 4.5.
Solusi:
Anda bisa menggunakan trik enum untuk menginisialisasi array di dalam definisi kelas Anda.
class A
{
static const int a = 3;
enum { arrsize = 2 };
static const int c[arrsize] = { 1, 2 };
};
Mengapa Standar tidak mengizinkan ini?
Bjarne menjelaskan hal ini dengan tepat di sini :
Kelas biasanya dideklarasikan dalam file header dan file header biasanya disertakan ke dalam banyak unit terjemahan. Namun, untuk menghindari aturan linker yang rumit, C ++ mengharuskan setiap objek memiliki definisi yang unik. Aturan itu akan rusak jika C ++ mengizinkan definisi entitas di kelas yang perlu disimpan dalam memori sebagai objek.
Mengapa hanya static const
tipe integral & enum yang diperbolehkan In-class Initialization?
Jawabannya tersembunyi dalam kutipan Bjarne. Bacalah dengan seksama,
"C ++ mengharuskan setiap objek memiliki definisi yang unik. Aturan itu akan rusak jika C ++ mengizinkan definisi entitas dalam kelas yang perlu disimpan dalam memori sebagai objek."
Perhatikan bahwa hanya static const
bilangan bulat yang dapat diperlakukan sebagai konstanta waktu kompilasi. Kompilator mengetahui bahwa nilai integer tidak akan berubah setiap saat dan karenanya ia dapat menerapkan sihirnya sendiri dan menerapkan pengoptimalan, kompilator hanya menyebariskan anggota kelas seperti itu, yaitu mereka tidak disimpan dalam memori lagi, Karena kebutuhan untuk disimpan dalam memori telah dihapus , itu memberikan variabel seperti pengecualian untuk aturan yang disebutkan oleh Bjarne.
Perlu dicatat di sini bahwa meskipun static const
nilai integral dapat memiliki In-Class Initialization, mengambil alamat variabel tersebut tidak diperbolehkan. Seseorang dapat mengambil alamat dari anggota statis jika (dan hanya jika) memiliki definisi di luar kelas. Ini selanjutnya memvalidasi alasan di atas.
enum diperbolehkan ini karena nilai dari tipe enumerasi dapat digunakan di mana int diharapkan. lihat kutipan di atas
Bagaimana ini berubah di C ++ 11?
C ++ 11 melonggarkan pembatasan sampai batas tertentu.
C ++ 11 9.4.2 Anggota data statis
§3
Jika anggota data statis berjenis const literal, deklarasinya dalam definisi kelas dapat menentukan brace-or-equal-initializer di mana setiap klausa penginisialisasi yang merupakan ekspresi-penugasan adalah ekspresi konstan. Anggota data statis tipe literal dapat dideklarasikan dalam definisi kelas dengan constexpr specifier;
jika demikian, deklarasinya harus menentukan brace-or-equal-initializer di mana setiap klausa penginisialisasi yang merupakan ekspresi penugasanadalah ekspresi konstan. [Catatan: Dalam kedua kasus ini, anggota mungkin muncul dalam ekspresi konstan. —End note] Anggota masih harus didefinisikan dalam lingkup namespace jika digunakan dalam program dan definisi ruang lingkup namespace tidak boleh berisi penginisialisasi.
Selain itu, C ++ 11 akan mengizinkan (§12.6.2.8) anggota data non-statis diinisialisasi di tempat ia dideklarasikan (di kelasnya). Ini berarti semantik pengguna yang lebih mudah.
Perhatikan bahwa fitur-fitur ini belum diimplementasikan di gcc 4.7 terbaru, Jadi Anda mungkin masih mendapatkan kesalahan kompilasi.