🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
在结构体定义中声明函数,稍后再定义函数,这看起来是一件麻烦事。任何时候你要改变一个函数的接口,都需要在两个地方做修改,即使只是做了很小的变动,比如把一个参数声明为const。 尽管如此,这种麻烦是有理由的,我们能够把结构体定义和函数分离到两个文件中:头文件包含着结构体定义,而实现文件包含着函数。 头文件通常和实现文件同名,但后缀是.h而不是.cpp。对于我们一直看的例子,头文件名为Time.h,它包含以下内容: ~~~ struct TIme { // 实例变量 int hour, minute; double second; //构造函数 Time (int hour, int min, double secs); Time (double secs); //修改器 void increment (double secs); //函数 void print () const; bool after (const Time& time2) const; Time add (const Time& t2) const; double convertToSeconds () const; }; ~~~ 请注意,我们并不需要在结构体定义中给每个函数名前面包含前缀Time::。编译器知道我们声明的函数是Time结构体的成员。 Time.cpp包含了成员函数的定义(为节省篇幅,我已经省去了函数体): ~~~ #include <iostream.h> #include "Time.h" Time::Time (int h, int m, double s) ... Time::Time (idouble secs) ... void Time::increment ( double secs) ... bool Time::after (const Time& time2) const ... Time Time::add (const Time& t2) const ... double Time::convertToSeconds () const ... ~~~ 在本例中,Time.cpp中的定义与Time.h中声明的顺序相同,这并非必要。 另一方面,有必要使用include语句将头文件包含进来。这样一来,当编译器读取函数定义时,它能足够了解结构体,便于检查代码并捕获错误。 最后,main.cpp包含了函数main,以及我们需要的非Time结构体的成员的函数(本例中没有): ~~~ #include <iostream.h> #include "Time.h" void main() { Time currentTime (9, 14, 30.0); currentTime.increment (500.0); currentTime.print (); Time breadTime (3, 35, 0.0); Time doneTime = currentTime.add (breadTime); doneTime.print (); if (doneTime.after (currentTime)) { cout << "The bread will be donw after it starts." <<endl; } } ~~~ 再一次,main.cpp必须包含头文件。 把如此小的程序分成三部分的好处也许并不明显。其实,大部分优点会在我们处理更大的程序时体现出来: **重用**:当你写了个类似于Time的结构,你也许会发现它在多个程序中都有用。通过把Time的定义从main.cpp中分离出来,在其它程序中包含Time结构会变得容易。 **管理交互**:随着系统变大,组件之间的交互数量快速增加,变得难以管理。通过从使用它们的程序中分离出Time.cpp这样的模块,可以最小化这些交互。 **独立编译**:单独的文件可以被独立编译,之后链接到一个程序中。其中的细节依赖于你的编程环境。随着程序规模变大,独立编译能节省很多时间,由于你通常每次只需要编译少数一些文件。 对于类似本书这样的小程序来说,分割程序并没有多大好处。但你最好知道这个特性,特别是它解释了我们写的第一个程序中出现的一个语句: ~~~ #include <iostream.h> ~~~ iostream.h是一个包含着cin和cout声明以及操作它们的函数的头文件,当编译程序时,你需要该头文件中的信息。 这些函数的实现存储在一个库中,有时候被称为"标准库",它能自动链接到你的程序中。好处在于当你编译程序时,你不需要每次都重新编译库。大多数情况下,库不会改变,因此没有理由重新编译它。