如何写出一个清晰,干净,整洁的C++头文件?
前言
使用C++编程时我们通常会在头文件中封装一些类,随着时间的推移,我们会发现头文件中include的其他头文件越来越多,类中的公开函数,私有函数,私有成员变量也越来越多。形成如下混乱的代码:
#include <lib0>
#include <lib1>
#include <lib2>
...
#include <libn>
class MyClass
{
public:
Myclass();
~MyClass();
void InterfaceA();
void InterfaceB();
...
void InterfaceZ();
private:
void PrivateA();
void PrivateB();
...
void PrivateZ();
private:
int m_value0;
int m_value1;
...
int m_valuen;
};
以上做法会给我们带来很多麻烦,如:
- 影响编译速度:因为我们的头文件引入了大量其他头文件,引入我们头文件的代码也相同引用了这些头文件,其中任何一个头文件被修改,代码就需要重新编译。
- 名称污染:这个依然是头文件大量包含引起的,引入我们头文件的代码被动引入了大量它不需要的头文件,可能导致定义的函数,类以及宏等会有命名上的冲突。
- 暴露细节:我们的私有成员变量和函数都在头文件中,使用我们头文件的人可以直观的看到这些,面向对象3要素中的封装就是需要我们隐藏细节。况且打开我们头文件查看接口的人看到大量的私有函数和私有成员变量也会很不舒服。
代理类
如何解决上面的问题?
- 使用代理类。
- 尽量只包含标准库的头文件。
我们在头文件中写下如下代码:
#include <vector>
#include <string>
class CMyClass;
class MyClass
{
public:
Myclass();
~MyClass();
void InterfaceA();
void InterfaceB();
...
void InterfaceZ();
private:
CMyClass* m_pMyClass;
};
我们在对应的CPP文件中写下如下代码:
#include <lib0>
#include <lib1>
#include <lib2>
...
#include <libn>
class CMyClass
{
public:
CMyclass();
~CMyClass();
void InterfaceA();
void InterfaceB();
...
void InterfaceZ();
private:
void PrivateA();
void PrivateB();
...
void PrivateZ();
private:
int m_value0;
int m_value1;
...
int m_valuen;
};
...
void MyClass::InterfaceA()
{
m_pMyClass->InterfaceA();
}
...
可以看到我们把大量的头文件放到在CPP文件中,这样可以解决头文件依赖的问题。MyClass中的公开函数都是在CMyClass类中实现的,MyClass只做一个转发的动作,所以MyClass中不会有大量的私有成员和私有函数。
代理类的缺点
虽然代理类可以帮我们解决这些问题,但是代理类也有一些缺点:
- 增加函数调用开销:因为函数被多转发一次所以性能上有一点点影响,但是这一点点影响在实际的项目中无足轻重。
- 额外的代码量:这个无法避免,这也是我们想要一个干净的头文件所需要付出的代价。
可以看看我在个人项目中的实践,头文件中只引入标准库和自己声明的一些结构:
后话
期待和大家一起学习和讨论。
还没有人评论...