Re: [問題] 一個專案使用兩種namespace

看板C_and_CPP作者 (-6.2598534e+18f)時間10年前 (2015/06/08 02:04), 10年前編輯推噓3(3033)
留言36則, 5人參與, 最新討論串2/2 (看更多)
仔細看了一下你的敘述我發現了一個很大的問題: InstantAI.h 裡面使用了 using namespace 一般來說 header file 裡不應該宣告全域的 using 敘述 因為這會造成所有引入這個標頭檔的檔案強迫把所 using 的東西給打開 (這有個名詞叫 namespace pollution, 命名空間污染) 在這裡你的 InstantAI.h 裡的宣告污染到了主程式 然後因為 Automation::BDaq 下面大概也有一個 uint8 (全名 Automation::BDaq::uint8) 但 winsock 裡的 uint8 是全域的 (全名 ::uint8) 而它的 macro 也許是展開成不帶 :: 的 uint8 造成編譯器看到不帶 :: 的 uint8 時找到了這兩個候選人 但他不知道你是指誰 (因為 Automation::BDaq::uint8 被 using 打開了) 所以就噴 C2872 沒理解錯的話 InstantAI.h 應該是你自己寫的檔案 這樣的話有兩個方法, 一個治標, 一個治本 治標法是把 InstantAI.h 裡那兩行 using namespace 移到 Datareadfunction() 裡面 這樣那就是函式區塊裡才有 using namespace 的效果 於是函式外面的 uint8 就只看得到 winsock 定的 ::uint8 治本法是你就不要留函式實作在 .h 裡了, 留宣告就好 另外開一個 .cpp 寫 Datareadfunction() using namespace 什麼的也移去那邊 最後編譯完再把兩個檔案連結起來 這樣兩個 .cpp 是各自的編譯單位, 誰都不會影響誰 -- 'Oh, Harry, don't you see?' Hermione breathed. 'If she could have done one thing to make absolutely sure that every single person in this school will read your interview, it was banning it!' ---'Harry Potter and the order of the phoenix', P513 -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 123.195.39.85 ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1433700253.A.0AA.html

06/08 03:43, , 1F
所以治本的辦法是將副程式改放在.cpp檔裡面 而不放在.h檔
06/08 03:43, 1F

06/08 03:44, , 2F
然後用主程式(寫在.cpp檔裡)去呼叫改寫在另一個.cpp檔裡
06/08 03:44, 2F

06/08 03:45, , 3F
的副程式Datareadfunction()?
06/08 03:45, 3F

06/08 03:46, , 4F
也就是把原本用.cpp呼叫.h檔的方式改成用.cpp呼叫.cpp檔?
06/08 03:46, 4F

06/08 05:15, , 5F
er...聽起來你要include cpp?這是大忌喔
06/08 05:15, 5F

06/08 10:16, , 6F
include 只是單純把程式碼串在一起而已
06/08 10:16, 6F

06/08 10:17, , 7F
串好的程式碼拿去編譯出來的目的檔就算呼叫未定義的函式
06/08 10:17, 7F

06/08 10:18, , 8F
編譯也不會有問題
06/08 10:18, 8F

06/08 10:20, , 9F
因為在連結並產生執行檔的階段,linker會試圖去解決
06/08 10:20, 9F

06/08 10:21, , 10F
兩個 CPP 檔意味著將會產生兩個目的檔
06/08 10:21, 10F

06/08 10:23, , 11F
而其中一個檔內的主程式會去呼叫另一個檔內的副程式
06/08 10:23, 11F

06/08 11:16, , 12F
global, namespace都有相同的typdef應該不會有問題才對
06/08 11:16, 12F

06/08 11:17, , 13F
http://ideone.com/Oze0ZM 像這樣也都不會有錯誤
06/08 11:17, 13F

06/08 11:21, , 14F
出現Ambiguous比較像Killercat提到的相同名稱有不同定義
06/08 11:21, 14F

06/08 11:23, , 15F
http://ideone.com/RSRQFd,此時只須明確定義要使用哪
06/08 11:23, 15F

06/08 11:24, , 16F
個namespace底下的uint8即可(XXXX::uint8 ...)。
06/08 11:24, 16F

06/08 11:29, , 17F
應該盡量避免將副程式寫在header檔裡,用前面說的header+
06/08 11:29, 17F

06/08 11:31, , 18F
cpp,h檔宣告prototype,cpp進行實作後linker會幫你處理。
06/08 11:31, 18F

06/08 12:08, , 19F
各位指的意思是 兩個.cpp檔不須互相include 只需要在專案
06/08 12:08, 19F

06/08 12:15, , 20F
各位指的意思是 兩個.cpp檔不須互相include 只需要在專案
06/08 12:15, 20F

06/08 12:16, , 21F
設定裡設定Linker副程式 然後主程式加上Datareadfunction
06/08 12:16, 21F

06/08 12:16, , 22F
() 就好了嗎?
06/08 12:16, 22F

06/08 13:09, , 23F
假設你main要使用void func(int a), 這時有三個檔案
06/08 13:09, 23F

06/08 13:09, , 24F
main.cpp xxx.h xxx.cpp, main include xxx.h
06/08 13:09, 24F

06/08 13:10, , 25F
xxx.h寫function protype, void func(int a);
06/08 13:10, 25F

06/08 13:11, , 26F
xxx.cpp對func進行實作, void func(int a) { //todo }
06/08 13:11, 26F

06/08 13:14, , 27F
但Ambious symbol問題還是可能存在,記得當type在不同
06/08 13:14, 27F

06/08 13:15, , 28F
namespace下都有定義且定義為不同的對象時,要明確指定你
06/08 13:15, 28F

06/08 13:17, , 29F
要使用哪個namespace下的,ex.Automation::BDaq::uint8 x
06/08 13:17, 29F

06/08 13:20, , 30F
不然編譯器看到他是A同時又是B會不知怎辦。
06/08 13:20, 30F
基本上正常來說 anyoiuo 提的方式才是使用 namespace 下的符號的正道 只是這裡不巧的是用它的人是 winsock 的 macro (大概就是 MAKEWORD) 那個 header 沒有考慮到 namespace 的問題 (或者根本就是 C header) 因此才必須要倒過來使用避免 namespace pollution 的方式把東西分開 ※ 編輯: LPH66 (140.112.30.32), 06/08/2015 15:51:11

06/08 16:51, , 31F
話說那行MACRO在windef.h
06/08 16:51, 31F

06/08 16:52, , 32F
長這樣((WORD)(((BYTE)(a))|(((WORD)((BYTE)(b)))<<8)))
06/08 16:52, 32F

06/08 18:00, , 33F
所以你拆開測ok嗎?
06/08 18:00, 33F

06/09 22:22, , 34F
anyoiuo大的方法看的不是很懂...進行實作的意思指的是編
06/09 22:22, 34F

06/09 22:23, , 35F
譯(build)?
06/09 22:23, 35F

06/10 01:19, , 36F
關鍵字: 多檔編譯, 再加上你所用的 IDE 下去 google
06/10 01:19, 36F
文章代碼(AID): #1LT8UT2g (C_and_CPP)
文章代碼(AID): #1LT8UT2g (C_and_CPP)