[問題] Namespace的用法問題

作者: a126040023 (肥宅中的魯蛇)   2016-02-09 18:06:15
開發平台:Xcode7.2
小弟最近開始接觸到namespace這個東西。由於對它不是很了解,只從書上大概了解他的
語法,我假設他的寫法跟class一樣是在.h做declaration 然後在.cpp做implementation
我看到很多書或是網站也都是這樣寫。但是我在.h對變數做宣告的時候,假如不加上
extern或static這兩個修飾詞的話都會出現編譯錯誤:duplicate symbol for
architecture x86_64
想請教一下為什麼會這樣?他跟class之間有什麼差別嗎?除了不能實體化之外。或著說
在compile時候compiler處理他跟處理class是什麼不同的方式啊。
ex:
__________Supplement.h____________
#ifndef Supplement_hpp
#define Supplement_hpp
#include <stdio.h>
#include <iostream>
#include <map>
using namespace std;
namespace MyNameSpace {
int i;
}
#endif /*Supplement_hpp */
_____________main.cpp______________
#include <stdlib.h>
#include "Supplement.hpp"
using namespace std;
int main(int argc, const char * argv[]) {
cout << MyNameSpace::i << endl;
}
上面這樣就會出現編譯錯誤。必須要把 int i 改成 extern int i才不會出現錯誤。
作者: LPH66 (-6.2598534e+18f)   2016-02-09 18:15:00
跟 namespace 無關, 你犯了在 .h 裡宣告全域變數的錯你把 namespace 拿掉一樣需要使用 extern 才行namespace 的概念就只是把「你的 i」「我的 i」「他的 i」給全部分開來, 變成用 You::i Me::i He::i 指名而已
作者: a126040023 (肥宅中的魯蛇)   2016-02-09 18:29:00
想請問一下 所以這樣會出錯原因是因為我已經在.cpp裡定義了一個全域變數 所以.h裡做宣告時後才會出錯嗎如果我.cpp都不寫任何code 單純在搬內宣告全域變數也會出錯 可是這樣子 duplicate是怎麼產生的呢?不好意思 上面打錯字 是指如果我單純在標頭宣告全域變數而不在.cpp定義變數 還是會出錯
作者: LPH66 (-6.2598534e+18f)   2016-02-09 19:43:00
你一定有別的檔案也 #include "Supplement.hpp"因為 #include 只是複製貼上, 所以多個檔案裡都會有同樣的東西, 於是連結時連結器會不知道這名字到底要給誰加 extern 的意思就是告訴連結器說「這東西到時會在別處,但這個名字幫我留個記號起來」, 這樣連結器才知道你要用誰
作者: fr3ak (fr3@K)   2016-02-09 21:26:00
推 LPH66. 魯叔也補充一下自己的理解方式. 對 object/variable 做 extern 可以視為把本來是 definition 的 statement轉變成 declaration. 而原 po 遇到的錯誤極有可能就是 LPH66 提到的多個 compilation unit 都 include 到該 definition, 等要 link 在一起的時候就出現重複的狀況了另再囉嗦幾句離題一下. IMHO, extern 能不用就不用. 用在 object/variable 上就是 global variable. 用在 function 上跟脫褲子放屁差不多概念. 有人跟我說過後者有 "就地" 引入的概念. 魯叔說, 不想討罵還是乖乖的去 include 正確的 header 吧 XD
作者: a126040023 (肥宅中的魯蛇)   2016-02-09 23:42:00
但其實我沒有include其他header耶 因為我就只有suppleSupplement.cpp, Supplement.hpp和main.cpp而已我發現把.cpp刪掉後就可以跑了可是我那檔案根本沒東西
作者: fr3ak (fr3@K)   2016-02-10 01:54:00
結案! Supplement.cpp 與 main.cpp 想必都有 include Supplement.h 吧 XD直接畫重點好了: 問題不是兩個 .cpp 去 include 同一個 .h,這是完全正常的. 而是該 header 的內容有問題 - 在 header裡面放了 i 的 definition. 所以那兩個各自去 include 該header 的 .cpp (or compilation unit to be more specific) 都乖乖的認份遵從 programmer 的指示, 對外主張自己擁有一份 i 的實體. 等到 link 的時候兩邊喬不攏就炸了啊 QQ
作者: a126040023 (肥宅中的魯蛇)   2016-02-10 23:27:00
哈我瞭解了 如果是這樣的話 那通常namespace寫法是把宣告和實作都寫在.h裡面而已 還是說分開寫啊
作者: LPH66 (-6.2598534e+18f)   2016-02-10 23:54:00
namespace 只是分別名字而已, 其他的實作什麼的完全照常

Links booklink

Contact Us: admin [ a t ] ucptt.com