2013-03-26 103 views
3

所以我正在學習C++並學習在我的實踐中使用SQLite來跨應用程序運行數據持久性,這非常有趣。C++ #include,嵌套如何包含工作?

但我撞上了這個問題:

該計劃是一個等級書,經典Ditel C++的書運動。我在我的結構化類如下:

~/classes/Database.h/cpp // A small wrapper for sqlite3 
~/classes/Student.h/cpp // The Student object with name and grades (Uses Database) 
~/classes/GradeBook.h/cpp // Takes care of most of the application logic and UI (Uses Database and Student) 
~/main.cpp // contains just the main function and base Instances of Database and GradeBook 

這是這樣我就可以從主實例化一個單個數據庫對象()和參照的GradeBook和學生傳遞這樣他們就可以使用數據庫功能。我嘗試了所有可能的包含順序,結果只有這個順序對我有用。

Student includes Database. 
GradeBook includes Student, gets access to Database. 
main.cpp includes GradeBook, gets access to both Database and Student. 

問題是,這是正確的嗎?這似乎完全違反直覺,包括似乎從最深層的類逐漸向main.cpp文件「倒退」,換句話說,我是這麼做的,還是我錯過了什麼?

如果是這樣,一個小小的解釋或指示如何「級聯」的作品將是非常棒的。

謝謝!

+0

爲什麼學生使用數據庫?看起來你可以改進它,以便成績冊使用數據庫和學生。 – perreal 2013-03-26 05:43:50

+0

我希望每個學生對象能夠保存自己的數據,以便從GradeBook中進行這些操作。 – 2013-03-26 05:46:25

+1

設計不健全。爲什麼學生堅持數據庫對象?考慮到這一點,數據庫是用於持久存儲的。 Student和GradeBook是永久性數據的快照,取自(不更改)或存儲到數據庫中。這並不意味着數據庫實例應該被這些數據所瞭解。理想情況下,數據庫將獨立於快照數據。快照數據是使用效用函數從數據庫「加載」的;無論是在類中的靜態函數還是實用程序類。那麼誰擁有數據庫實例?無論誰負責管理學生和GradeBook。 – 2013-03-26 05:47:04

回答

5

首先,你的頭文件應該使用包括防護,以防止多個包含:

#ifndef MY_HEADER_H 
#define MY_HDEADER_H 

// code... 

#endif // this file will only ever be copied in once to another file 

其次,你應該明確包括所有你需要做你想要做什麼的頭文件。依靠標題A爲您添加標題B非常笨重,因爲您使用的是包含標誌,所以您不必擔心將同一文件包含兩次。

因此,要回答你的問題,不,從某種意義上說,它可能是「更好的」並不是「正確的」。 main.cpp應該包含它需要的所有頭文件。他們全部。 #include是一個簡單的文本替換機制。當你將一個文件粘貼到文件中時,就是這樣。

+1

我認爲主要問題是確定實際需求。根據您的建議,OP可能會適應使用過多包含語句的壞習慣。 – perreal 2013-03-26 05:48:13

+2

@perreal:我不同意。包含您需要的文件沒有任何「過度」。你不應該依靠一個頭來爲你包括另一個頭,你應該明確。沒有任何成本,並且您的代碼因爲它而更加健壯。如果沒有充足的理由,不要依賴當前實現的另一個頭。而且,包括守衛在內也不是問題。 – 2013-03-26 05:52:18

+0

所以,另一件事:爲什麼如果我在main.cpp的頂部導入Database.h,它對後來導入的學生是不可見的? – 2013-03-26 05:54:19