尽量不要在头文件中包含另外的头文件

73 篇文章 5 订阅
70 篇文章 2 订阅

//原创文章,不得转载

 

这是一个原则!

通常当用到一个类的时候,我们会在文件头开头处包含相关类的头文件如:

//user.h

class CUser

{

 pulic:

      char m_strchUserName[100];

       int   m_nUserID;

}

 

 

 

//meeting.h

 

#include"user.h"

 

class CMeeting

{

pulic:

CMeeting();

~CMeeting();

 

    CUser *  m_User[100];

 

   void   add_user( CUser * pUser  , int i );

}

 

//meeting.cpp

CMeeting::CMeeting()

{

}

 

CMeeting::~CMeeting()

{

}

 

void  CMeeting::add_user( CUser * pUser  , int i )

 

{

          m_User[ i ] = pUser;

}

 

从上述例子中,可以看到标准的,一般的做法,在meeting.h头文件中包含user.h, 因为 这里用到了CUser类。

一般在用到相应类型的时候,自然的会去包含响应的头文件。

 

下面,解释一下:尽量不要在头文件中包含另外的头文件,而是对对序下文中可能用到的类进行前置声明(forward declaration)。

引用书上的一段话:

对程序下文中可能用到的类进行前置声明(forward declaration)。

它们会告诉编译器,我们用到的这些类已经存在了,并且不需要知道这些类的完整定义。

我们为什么要这样做,而不是将它们的头文件包含进来呢?

这主要是由于在程序下文中,我们只是简单的定义了指向这些类的对象的指针,而并没有涉及到该类的其他方面。


这样做的好处:

一是:避免了头文件被其他文件多次包含,尤其是在头文件中包含头文件时,容易造成重复包含和产生包含顺序问题,并且增大了文件的体积;

二是:提高了编译速度,因为编译器只需知道该类已经被定义了,而无需了解定义的细节。

 

一种好的编程风格是,尽量在头文件中使用类前置声明程序下文中要用到的类,实在需要包含其它的头文件时,可以把它放在我们的类实现文件中。

关于前置声明,可以参考其它文章。

 

根据这个原则,可以将上述例子修改为:

 

 

//meeting.h

 

class CUser;    //#include"user.h"   //在头文件中,将文件包含修改为类的前置声明;

 

class CMeeting

{

pulic:

CMeeting();

~CMeeting();

 

    CUser *  m_User[100];

 

   void   add_user( CUser * pUser  , int i );

}

 

//meeting.cpp

#include"user.h"      //在cpp文件中添加类的包含;

CMeeting::CMeeting()

{

}

 

CMeeting::~CMeeting()

{

}

 

 

 

void  CMeeting::add_user( CUser * pUser  , int i )

{

          m_User[ i ] = pUser;

}

 

 

从修改的程序看,如果CMeeting类 和 CUser类 是封装在一个 动态链接库(dll)中的两个类。

 CMeeting是导出类。

导出的dll为, UserMeeting.dll;

 

这样就可以实现CUser类细节的封装到dll中,同时减少外部文件依赖。

导出C++ 类中,除了基本数据类型直接声明;

自定义类型非常建议用类型指针;

 

 

 

 

在看一个示例:

如果编写一个dll,头文件的方式,可以是这样:

 

//h文件;

class api_Test

{

public:

 void test_func1();


pbulic:

void set_param( int param );

int get_param();

 

 

private:

//cpp文件中api_Test_member_param *转换void * 类型;

void * m_handle;

或者:

//前置声明api_Test_member_param;

//虽然这样简单,利于dll工程编写,但是对外的文件,显示的信息太多没有必要;

api_Test_member_param * m_handle;

 

 

}

 

//cpp

struct api_Test_member_param

{

 int  n1;

int n2;

char *  pstr1;

}

 

static api_Test_member_param * change_handl_to_param(void * param)

{

return (api_Test_member_param *) param;

}

 

//如果想要编写更简单,可以宏定义一下函数,放到cpp上面:

//#define 是直接替换,所以参数直接用m_handle;

//可以直接用PARAM获取参数;

#define  PARAM  change_handl_to_param(m_handle)

 

 

 

 

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

chinabinlang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值