Pemahaman saya adalah bahwa C ++ memungkinkan anggota konstanta statis untuk didefinisikan di dalam kelas selama itu adalah tipe integer.
Lalu, mengapa kode berikut memberi saya kesalahan penaut?
#include <algorithm>
#include <iostream>
class test
{
public:
static const int N = 10;
};
int main()
{
std::cout << test::N << "\n";
std::min(9, test::N);
}
Kesalahan yang saya dapatkan adalah:
test.cpp:(.text+0x130): undefined reference to `test::N'
collect2: ld returned 1 exit status
Menariknya, jika saya mengomentari panggilan ke std :: min, kode mengkompilasi dan tautan dengan baik (meskipun test :: N juga direferensikan pada baris sebelumnya).
Tahu apa yang terjadi?
Kompiler saya adalah gcc 4.4 di Linux.
c++
static
declaration
definition
Komandan Tinggi4
sumber
sumber
char
, Anda dapat mendefinisikannya sebagaiconstexpr static const char &N = "n"[0];
. Perhatikan&
. Saya kira ini berfungsi karena string literal didefinisikan secara otomatis. Saya agak khawatir tentang ini - ini mungkin berperilaku aneh di file header di antara unit terjemahan yang berbeda, karena string mungkin akan berada di beberapa alamat berbeda.inline const int N = 10
, yang menurut pengetahuan saya masih memiliki penyimpanan di suatu tempat yang ditentukan oleh linker. Kata kunci sebaris juga dapat digunakan dalam kasus ini untuk memberikan definisi variabel statis di dalam pengujian definisi kelas.Jawaban:
Pemahaman saya adalah bahwa C ++ memungkinkan anggota konstanta statis untuk didefinisikan di dalam kelas selama itu adalah tipe integer.
Anda agak benar. Anda diizinkan untuk menginisialisasi integral konstanta statis dalam deklarasi kelas, tetapi itu bukan definisi.
http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=/com.ibm.xlcpp8a.doc/language/ref/cplr038.htm
Menariknya, jika saya mengomentari panggilan ke std :: min, kode mengkompilasi dan tautan dengan baik (meskipun test :: N juga direferensikan pada baris sebelumnya).
Tahu apa yang terjadi?
std :: min mengambil parameternya dengan referensi const. Jika mengambil nilai, Anda tidak akan mengalami masalah ini, tetapi karena Anda memerlukan referensi, Anda juga memerlukan definisi.
Berikut pasal / ayatnya:
9.4.2 / 4 - Jika anggota
static
data adalahconst
integral atauconst
tipe enumerasi, 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 .Lihat jawaban Chu untuk solusi yang mungkin.
sumber
5
ke aconst int&
. Jadi mengapa tidak memperlakukan OPtest::N
sebagai literal yang sesuai?Contoh Bjarne Stroustrup dalam C ++ FAQ-nya menunjukkan bahwa Anda benar, dan hanya perlu definisi jika Anda mengambil alamatnya.
Dia mengatakan "Anda dapat mengambil alamat dari anggota statis jika (dan hanya jika) memiliki definisi di luar kelas" . Yang menunjukkan itu akan berhasil sebaliknya. Mungkin fungsi min Anda memanggil alamat di balik layar.
sumber
std::min
mengambil parameternya dengan referensi, itulah sebabnya definisi diperlukan.template<class K, class V, class C> const typename AE<K,V,C>::KeyContainer::size_type AE<K,V,C>::c7;
dimana KeyContainer adalah typedef dari std :: vector <K>. Seseorang harus membuat daftar semua parameter template dan menulis nama jenis karena itu adalah jenis yang bergantung. Mungkin seseorang akan menganggap komentar ini berguna. Namun, sekarang saya bertanya-tanya bagaimana cara mengekspor ini dalam DLL karena kelas template tentu saja di header. Apakah saya perlu mengekspor c7 ???Cara lain untuk melakukan ini, untuk tipe integer, adalah dengan mendefinisikan konstanta sebagai enum di kelas:
sumber
Bukan hanya int. Tetapi Anda tidak dapat menentukan nilai dalam deklarasi kelas. Jika Anda memiliki:
di file .h maka Anda harus memiliki:
di file .cpp.
sumber
static const
anggota integral dalam definisi kelas. Tapi itu tetap tidak mendefinisikan anggota itu. Lihat jawaban Noah Roberts untuk detailnya.Berikut cara lain untuk mengatasi masalah tersebut:
(Saya pikir jawaban Crazy Eddie dengan tepat menjelaskan mengapa masalah itu ada.)
sumber
std::min(9, +test::N);
Mulai C ++ 11 Anda dapat menggunakan:
static constexpr int N = 10;
Ini secara teoritis masih mengharuskan Anda untuk mendefinisikan konstanta dalam file .cpp, tetapi selama Anda tidak mengambil alamatnya
N
, sangat tidak mungkin implementasi compiler apa pun akan menghasilkan kesalahan;).sumber
Tidak, 3.1 §2 mengatakan:
sumber