baizy77 发表于 2018-9-16 22:56:35

C++老鸟日记023 如何避免修改头文件时导致项目重新编译

本帖最后由 baizy77 于 2018-10-1 20:55 编辑

版权声明---------------------------------------------------------------------------------------------------------------------该文章原创于Qter开源社区(www.qter.org)作者: 女儿叫老白 (白振勇)转载请注明出处!---------------------------------------------------------------------------------------------------------------------课程目录:《C++老鸟日记》目录本套课程属于:《C++跨平台开发干货》系列课程。-----------------------------------------------------------------------------
引言:----------------------------------------------------------------------------       我们都知道,在使用某个class或者struct的时候,需要包含这个class或者struct所在的头文件,以便成功编译。但是,如果在一个大型项目中,代码动辄几十万行,如果一旦修改头文件,就会导致包含该头文件的所有文件都要重新编译,这将耗费非常多的时间。那么,怎样才能尽可能防止重新编译呢?
正文:----------------------------------------------------------------------------       很多童鞋马上想到了使用增量编译。其实,对我们来说增量编译是基本的设置,因此我们这里假定已经使用了增量编译。那么还有什么方法可以做到吗?       答案是,当然有了。       我们在头文件中使用某个class的时候,如果不是使用对象而是使用指向对象的地址的指针,那么我们就可以轻松做到避免不必要的编译了。       假定类型CMyClass是在他处定义的类,我们的代码如下:
// user.h

#include myclass.h       // CMyClass所在的头文件
class CUser {
public:
       ……
public:
       string getInfo(CMyClass& obj); // 此处用到了CMyClass
};

// user.cpp
#include “user.h”
string CUser::getInfo(CMyClass& obj) {
    pObj->xxx();
}
       在上述代码中,”user.h”中,因为接口getInfo使用CMyClass定义了对象,因此编译器必须知道该对象是什么样子,所以它要求我们包含myclass.h以便知道其具体定义。但是,一旦CMyClass的定义发生变化,那么user.h将被重新编译,这会导致所有包含user.h的文件都被重新编译。这是没有必要的,而且浪费编译时间。
       我们可以换用另一种设计,把对象改为指针,具体代码如下:// user.h
class CMyClass;   // CMyClass的声明,用来告诉编译器,CMyClass是一个类,但是在其他地方已定义。
class CUser {
public:
      ……
public:
      string getInfo(CMyClass* pObj); // 此处用到了CMyClass*的指针
};
// user.cpp
#include “user.h”
#include “myclass.h” // 仅需要在cpp中包含该头文件即可
string CUser::getInfo(CMyClass* pObj) {
}

    在改动后的代码中,在user.h中,getInfo() 接口不再使用CMyClass对象,而是使用CMyClass定义了一个指针。因此仅需要在user.h的开头部分使用前向声明把CMyClass声明一下即可。在真正使用的地方是在user.cpp中,因为getInfo需要使用CMyClass指针调用接口,所以在user.cpp中增加了 #include “myclass.h”。这样就无需在user.h中包含myclass.h了。
结语:----------------------------------------------------------------------------       我们所作的改动设计:在头文件的接口中使用指针传递参数,在头文件开头部分使用前向声明。这种设计,将CMyClass改动时影响的代码范围控制到最小(在本例中,仅影响user.cpp,而不会影响user.h,否则会连带影响包含user.h的代码)。建议大家使用前向声明的方式使用引入的类,避免直接#include 类的头文件。

参考资料----------------------------------------------------------------------------《C++编程思想》两卷合订本中文版(5.6.2章节),(美) Bruce EckelChuck Allison著

miroox 发表于 2018-9-17 15:48:59

也就是所谓的pImpl呗

baizy77 发表于 2018-9-17 17:22:45

miroox 发表于 2018-9-17 15:48
也就是所谓的pImpl呗

您给的文章很好。推荐。

tan 发表于 2018-9-21 08:08:33

string getInfo(CMyClass& obj);    此处是引用么?   如果是引用也箱单于指针么?

baizy77 发表于 2018-9-21 08:36:46

tan 发表于 2018-9-21 08:08
string getInfo(CMyClass& obj);    此处是引用么?   如果是引用也箱单于指针么?

...

是引用。作用跟指针完全一样。唯一的不同是使用引用的语法,可以使代码看上去更像是对一个对象操作,因为使用指针时需要用->。

tan 发表于 2018-9-22 11:03:07

baizy77 发表于 2018-9-21 08:36
是引用。作用跟指针完全一样。唯一的不同是使用引用的语法,可以使代码看上去更像是对一个对象操作,因为 ...

ok                                 
页: [1]
查看完整版本: C++老鸟日记023 如何避免修改头文件时导致项目重新编译