Re: [問題] struct static const member link error

看板C_and_CPP作者 (Cary)時間9年前 (2015/01/21 12:02), 9年前編輯推噓1(100)
留言1則, 1人參與, 最新討論串2/2 (看更多)
※ 引述《shininglion (lionking - 辛巴)》之銘言: : 開發平台(Platform): (Ex: VC++, GCC, Linux, ...) : Ubuntu 14.04, g++ v4.8.2 : 問題(Question): : link error, undefined reference to XXX : 程式碼(Code):(請善用置底文網頁, 記得排版) : 問題程式碼如下,分在兩個檔案 : [fileA.h] : struct A : { : static const int val = 0; : }; : [fileB.cpp] : /* something */ : std::unordered_map<int, std::string> umap; : /* somthing */ : const std::string str = umap.at(A::val) + "123"; // error here : 上面那行就是我的問題所在 : 因為 A::val 是 A 的 static const member,所以語法上應該是沒問題的 : compile 也確實有過,但是 link 時就噴 error 說找不到 A::val : 後來我把 fileB.cpp 的那一段改成下面這樣就過了: : [fileB.cpp] : /* something */ : std::unordered_map<int, std::string> umap; : /* something */ : const int VAL = A::val; : const std::string str = umap.at(VAL) + "123"; // pass : 我想不出原因為什麼一開始的寫法會 link error : 但是改成下面這種寫法就過了 : 想請問有版友知道原因嗎? : 謝謝! 根據標準(2003 版的 9.4.2.4) If a static data member is of const integral or const enumeration type, its declaration in the class definition can specify a constant-initializer which shall be an integral constant expression (5.19). In that case, the member can appear in integral constant expressions. The member shall still be defined in a namespace scope if it is used in the program and the namespace scope definition shall not contain an initializer. 所以最標準的寫法是,你應該要在 class 實作的地方(ex:fileA.cpp)加上這行 const int A::val; 至於為什麼另外 assign 到其他變數就可行而傳進 at 卻不行? 我猜是因為 static const int 有可能並沒有 allocate memory at 接收的是一個 reference,當然會找不到。 而另外 assign 或是加上可以產生 temporary variable 的方法都可以繞過。 不過最正確的方法還是明確給他個 definition。 補上 11 標準的 9.4.2.3 If a non-volatile const static data member is of integral or enumeration type, its declaration in the class definition can specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression (5.19). A static data member of literal type can be declared in the class definition with the constexpr specifier; if so, its declaration shall specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression. [ Note: In both these cases, the member may appear in constant expressions. — end note ] The member shall still be defined in a namespace scope if it is odr-used (3.2) in the program and the namespace scope definition shall not contain an initializer. -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 1.34.244.41 ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1421812929.A.05F.html ※ 編輯: carylorrk (1.34.244.41), 01/21/2015 12:09:53

01/21 16:54, , 1F
謝謝解答,問題已確實解決. 看來以前是運氣好沒遇到
01/21 16:54, 1F
文章代碼(AID): #1KloJ11V (C_and_CPP)
文章代碼(AID): #1KloJ11V (C_and_CPP)