2013-03-26 99 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