看板 C_and_CPP 關於我們 聯絡資訊
※ 引述《kyoiku (所有狗類的主人)》之銘言: : 「要引入正確的標頭檔才能使用裡面所定義的函式」 宣告 : 例如寫上 #include <math.h> 就可以引用 math.h 裡面所有的函式。 : 可是對於剛接觸 C++ 的人來說, : 他不太清楚所寫的程式會引用到哪個標頭檔。 math 這個英文字是數學的意思, 表示在 math.h這個標頭檔裡宣告 的是有關數學運算的函式 string.h 則是字串處理的函式宣告s stdio.h 則是 standard input/output 相關的函式宣告s 所以你想要達成怎樣的功能, 就先聯想到有關的標頭檔, 再去查裡 面是否有你可以呼叫來用的函式, 通常初學也只有以下幾個標頭檔 會比較常用到: ctype.h limits.h math.h stdio.h stdlib.h string.h time.h 你要先學著大概記住他們的分類依據, 這也是為什麼檔案命名也是 非常重要的原因, 可以作有效的管理. : 所以我想說能不能把所有標頭檔在開始就都一股作氣全寫上去? : 不管要寫什麼程式,像這樣: : #include <math.h> : #include <iostream.h> : #include <iostream> : ... : ... : ... : 就先存起來複製貼上,雖然無腦但也省了找對應標頭檔的時間, : 可是看了一堆程式碼都沒看到這樣的用法? : 是高手不屑這樣用還是這樣用會出啥問題呢,@@? 先不考慮編譯的效率是怎樣, 程式碼裡的每一行指令都寓意深遠. 先來看下面的例子, 有 4個檔案分別為 first.h、second.cpp、 third.h、fourth.cpp: - // first.h struct a { int x, y; }; - // second.cpp #include "first.h" // some code here .... - // third.h #include "first.h" struct b { a qq; int t, u; }; - // fourth.cpp #include "third.h" // some code here ... 由上面的程式碼我們可以得到一個檔案的相依關係圖: ┌────┐ │ first.h│ └────┘ ↗ ↖ ┌─────┐ ┌────┐ │second.cpp│ │ third.h│ └─────┘ └────┘ ↑ ┌─────┐ │fourth.cpp│ └─────┘ 箭頭表示的關係是: 相依端 → 被相依端, 在你開始寫自己的標 頭檔後, 這樣的關係必須非常清楚. 在這樣樹狀圖中, 下面的檔案可能會呼叫上方檔案內的函式, 甚 至是使用裡面的資料結構來建立物件, 現在如果 first.h裡的結 構 a要增加一個成員 int z, 因為這樣的相依關係, 所有下游的 second.cpp、fourth.cpp很可能都要重新編譯才能因應改變, 來 做功能的更新; 但去修改結構 b卻只會影響 fourth.cpp 一個檔 案. 一個程式都是由你寫不會有什麼問題, 但是在多人分工的情況下 , 就需要良好的相依結構. 你的問題雖然是引入標準函式庫的標 頭檔(幾乎不再改變), 但還是建議你從初學就養成良好的習慣, 不然如果寫成這樣: ┌────┐ ┌────┐ │ first.h│← │ third.h│ └────┘ └────┘ ↑ ↗↖ ↑ ┌─────┐ ┌─────┐ │second.cpp│ │ fourth.h │ └─────┘ └─────┘ 哪天你不小心呼叫了不相干標頭檔裡的函式而不自知, 對方假如 對他提供的標頭檔常常作改版, 包準你重編譯到哭出來... - 另外, 附上我自己的一個心得, 在一個檔案最前面引入標頭檔, 也可以對讀者做「心理建設」, 這等於是在跟他說: 「在看這份 程式碼之前, 可能要先對以下這些標頭檔的內容有個簡單的認識 喔!」,通常對引入很多檔案的程式碼, 你讀懂他所要付出的努力 也是相對多的. -- ▂▂ ▄▂ T.T.L Listen 2 http://ppt.cc/jIUk ˇ ˇˇ ˇ 說什麼結束 ▃▃ http://ppt.cc/zQtB ψ髮箍 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 140.121.197.115
uranusjr:第一個例子有點問題, 看不出來為什麼 third 要 include 04/08 19:53
uranusjr:first... 04/08 19:53
程式碼已補上
uranusjr:在 header 裡引用 header 應該要盡可能避免吧 04/08 19:53
利用composite來建構資料型態即有可能會發生 #if !defined(MY_STACK_H) #define MY_STACK_H #include <vector> struct MyStack { private: std::vector<int> container; // ... }; #endif
nowar100:"避免header引用header"印象中是歷史的說法 印象中現在 04/08 20:23
nowar100:提倡要讓別人include該功能header即可,因此內部應該難以 04/08 20:23
nowar100:避免再去包其他header的狀況吧 04/08 20:23
Ebergies:看所謂的功能而定,標頭能少加就少加,尤其大型專案 04/08 20:29
VictorTom:小弟我比較受不了的是, 在某個c.c裡, #include b.h之上 04/08 20:44
VictorTom:還得自己知道要#include a.h這種情況, b需要a的話直接讓 04/08 20:45
VictorTom:b.h裡 #include a.h就好了嘛Orz 只是這就撞到.h inc .h 04/08 20:46
VictorTom:的情況. 目前是不太清楚這樣寫有什麼負面影響@_@" 04/08 20:46
Ebergies:因為 c.c 不見得需要 a.h 的東西,如果 c.c 只用到 b.h 04/08 20:57
Ebergies:的其他功能,那麼沒有道理 a.h 變動 c.c 也要跟著編吧 04/08 20:58
Ebergies:而如果 b.h 確實跟 a.h 密不可分,那包一下也沒關係 LOL 04/08 21:02
補一個箭頭...
littleshan:header include header 是很正常的事 04/08 21:53
littleshan:如果要避免過複雜的 dependency 拉長編譯時間 04/08 21:54
littleshan:可以用 forward declaration + pimpl 來解決 04/08 21:54
個人覺得 forward declaration 不錯, pimpl撰寫上又多了複雜性 , 除非必要我真的會避免用它 Orz...
littleshan:V板友說的那個問題 的確應該要讓b.h去include a.h 04/08 22:00
littleshan:不然萬一b.h增加了某些功能 又包含了c.h 04/08 22:00
littleshan:那所有用到b.h的檔案都要改 會死人 04/08 22:00
※ 編輯: loveme00835 來自: 140.121.197.115 (04/08 22:02)
Ebergies:樓上說的包含 c.h 問題其實是一樣的因為如果你原本就 04/08 22:12
Ebergies:用不到 c.h, 那麼用到 b.h 的檔案不用修改就可以編過 04/08 22:13
Ebergies:而如果你要用 c.h 的功能, 那本來就要去改動檔案了 04/08 22:13