Re: [問題] 關於typedef

看板C_and_CPP作者 ( )時間13年前 (2010/10/04 21:17), 編輯推噓7(7027)
留言34則, 7人參與, 最新討論串3/6 (看更多)
先不說把 * 藏起來的問題。 如果你在寫 C++ 的話, 這類 typedef 其實是一個非常麻煩的東西。 因為... --------------------------------------------------- // node.hxx typedef struct node { int value; struct node *prev; struct node *next; } Node; void NodeAPI1(Node *); void NodeAPI2(Node *, Node *); ... --------------------------------------------------- // node_client.hxx struct Node; void foo(Node *); ... --------------------------------------------------- // node_client.cxx #include "node.hxx" #include "node_client.hxx" void foo(Node *n) { // 這邊會存取到 n->value 等內部欄位 } ... --------------------------------------------------- 編譯後得到錯誤訊息: In file included from node_client.cxx:4: node_client.hxx:3: error: using typedef-name 'Node' after 'struct' node.hxx:7: error: 'Node' has a previous declaration here 調換 node_client.cxx 兩行 #include 順序的話: In file included from node_client.cxx:4: node.hxx:7: error: conflicting declaration 'typedef struct node Node' node_client.hxx:3: error: 'struct Node' has a previous declaration as 'struct Node' 一種解決方案是拔掉 node_client.hxx 的前置宣告, 然後讓它直接去 #include "node.hxx"。 但這樣做的話就會增加編譯期相依性, 任何寫到 #include "node_client.hxx" 的檔案, 只要 node.hxx 修改就會被重新編譯。 這也是為什麼 node_client.hxx 一開始會打算放前置宣告的原因。 所以 C++ 其實不是很喜歡這種 typedef 的用法, typedef 在 C++ 一般比較常被用在 template 相關的 code 上。 一開始的寫法其實用純 C compiler 可以編譯通過, 不過 GCC 4.5 開始能用 gcc -Wc++-compat 得到警告訊息: In file included from node_client.c:4:0: node_client.hxx:3:8: warning: using 'Node' as both a typedef and a tag is invalid in C++ node.hxx:7:3: note: originally defined here -- Ling-hua Tseng (uranus@tinlans.org) Department of Computer Science, National Tsing-Hua University Interesting: C++, Compiler, PL/PD, OS, VM, Large-scale software design Researching: Software pipelining for VLIW architectures Homepage: http://www.tinlans.org -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 118.160.107.243 ※ 編輯: tinlans 來自: 118.160.107.243 (10/04 21:18)

10/04 21:30, , 1F
好像搞得很複雜,這樣程式碼很難維護,可讀性也不高...
10/04 21:30, 1F

10/04 21:31, , 2F
該include就include吧 犧牲一些compile time還好吧 除非
10/04 21:31, 2F

10/04 21:33, , 3F
加了那個前置宣告可以讓你compile time從一天縮短到幾小時
10/04 21:33, 3F

10/04 21:34, , 4F
而且你的Makefile也會變得很複雜 還是專注在寫程式好 XD
10/04 21:34, 4F

10/04 21:39, , 5F
其實編譯時間時嚜的還是其次, 重點是「增加相依性」的
10/04 21:39, 5F

10/04 21:41, , 6F
要不然乾脆直接把他做成 share library 只要 link XD
10/04 21:41, 6F

10/04 21:41, , 7F
問題, 造成維護上的麻煩
10/04 21:41, 7F

10/04 21:43, , 8F
本來就是相依的 程式都連在一起 你怎樣做都相依 = =""
10/04 21:43, 8F

10/04 21:44, , 9F
重點就在於編譯時間 是不是每次改動一點就要全部重編 = =
10/04 21:44, 9F

10/04 21:45, , 10F
還是只要重編改過的 然後link進去就好
10/04 21:45, 10F

10/04 21:47, , 11F
這樣寫維護性才不高 下一個看code的人 很難看懂
10/04 21:47, 11F

10/04 21:48, , 12F
要追一下才會知道那個前置宣告到底定義在哪?? node.hxx
10/04 21:48, 12F

10/04 21:52, , 13F
不是吧,重點是根本不該那樣 typedef 吧,就全都可以避免
10/04 21:52, 13F

10/04 21:52, , 14F
相依性有分強弱, 編譯的時間還可以用防火牆來擋, 為了
10/04 21:52, 14F

10/04 21:53, , 15F
方便追亂引入, 等到ADL你就知道
10/04 21:53, 15F

10/04 21:53, , 16F
C編譯器太鬆了,這樣寫也能通過,在Windows可以用cppcheck
10/04 21:53, 16F

10/04 21:54, , 17F
對前制處理後(cl.exe /E)的檔案做靜態程式碼分析抓出問題
10/04 21:54, 17F

10/04 21:54, , 18F
會回報Struct 'Node' hides typedef with same name
10/04 21:54, 18F

10/04 21:55, , 19F
loveme00835 ... Orz
10/04 21:55, 19F

10/04 21:55, , 20F
10/04 21:55, 20F

10/04 21:56, , 21F
love 大大 Orz
10/04 21:56, 21F

10/04 22:06, , 22F
@_@ 怎麼了嗎? 囧rz
10/04 22:06, 22F

10/04 22:07, , 23F
會出現前置宣告,除了降低編譯期相依性,也是告訴使用該
10/04 22:07, 23F

10/04 22:07, , 24F
header 的人,不需要知道 Node 細節。只要操作 Node *
10/04 22:07, 24F

10/04 22:08, , 25F
這種不透明的型別,和使用 foo() 這種 API 就可以了。
10/04 22:08, 25F

10/04 22:09, , 26F
如果 node_client.hxx 是很基礎的 utility header,用到它
10/04 22:09, 26F

10/04 22:10, , 27F
的有幾十個 .cxx。要是直接 #include "node.hxx",
10/04 22:10, 27F

10/04 22:10, , 28F
那就是大規模的重編譯。
10/04 22:10, 28F

10/04 22:11, , 29F
↑ 如果動到 node.hxx 的話。
10/04 22:11, 29F

10/04 22:33, , 30F
所以才會有Pimpl idom這種手法出現, 不過也是少用為妙
10/04 22:33, 30F

10/04 22:58, , 31F
i
10/04 22:58, 31F

10/04 23:02, , 32F
tinlans大最後的推文說明完,比較懂這種設計的考量原因了
10/04 23:02, 32F

10/05 08:58, , 33F
今天花點時間看懂了,推一下
10/05 08:58, 33F

10/05 12:09, , 34F
不過ADT好像常常用這種手法= =a 搞的維護者很難看懂程式碼
10/05 12:09, 34F
文章代碼(AID): #1CgTFtUn (C_and_CPP)
文章代碼(AID): #1CgTFtUn (C_and_CPP)