作者loveme00835 (朴髮箍)
看板C_and_CPP
標題Re: [問題] 新手關於 #include 的問題
時間Fri Apr 8 19:39:31 2011
※ 引述《kyoiku (所有狗類的主人)》之銘言:
: 「要引入正確的標頭檔才能使用裡面所定義的函式」
宣告
: 例如寫上 #include <math.h> 就可以引用 math.h 裡面所有的函式。
: 可是對於剛接觸 C++ 的人來說,
: 他不太清楚所寫的程式會引用到哪個標頭檔。
math 這個英文字是
數學的意思, 表示在 math.h這個標頭檔裡宣告
的是有關數學運算的函式
string.h 則是
字串處理的函式宣告s
stdio.h 則是
standar
d 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