通俗易懂----C++前置声明

大型开发都会遇到的问题

随着软件规模的扩大,包含在一个工程中的模块的数量在不断增长,模块之间的依赖关系也日益复杂。这里只举一个相对简单的例子:一个包含2个类,5个文件的工程。

ImportantClass.h

通俗易懂----C++前置声明

头文件中声明了构造函数,doWork成员函数和数据成员buffer。

 

ImportantClass.cpp

cpp文件中为构造函数和doWork提供了最简单的实现。

通俗易懂----C++前置声明

userclass.h

通俗易懂----C++前置声明

声明了构造函数,析构函数和doSomething成员函数以及ImportClass类型的数据成员。由于ip是ImportClass的实例,所以构建UserClass的声明中需要ImportantClass头文件(包含类结构信息)。

 

userclass.cpp

通俗易懂----C++前置声明

userclass.cpp为构造函数,析构函数和doSomething成员函数提供了最简单的实现。

 

main.cpp

通俗易懂----C++前置声明

代码中创建了一个UserClass对象并调用了它的doSomething成员函数。

 

为了理解上述代码中的问题,首先明确一件事:一般来讲C++编译器编译的编译对象是工程中的那些cpp文件。.h文件一边不会单独编译,而是和包含它的cpp文件一起编译。具体到例子工程,可以大致如下理解:

importclass.cpp在编译时同时编译了importclass.h文件。

userclass.cpp在编译时同时编译的userclass.h文件和importclass.h文件。

main.cpp在编译时同时编译了userclass.h和importclass.h文件。

 

上面代码中的主要问题是main.cpp真正希望使用的是UserClass,但由于userclass.h又引用了importantclass.h,所以产生了额外的依赖关系。

 

除了main.cpp以外,importclass.cpp和userclass.cpp中实际会使用到ImportClass类,这两处依赖关系是必要的。

 

前置声明

上述问题的解决方法就是前置声明,具体代码如下。

通俗易懂----C++前置声明

代 码中的变化有两点,一个是数据ImportantClass成员的类型变成了指针类型;另一个是include语句变成了class声明语句。两个变化缺 一不可,第二个变化是第一个变化的前提条件。因为这里只是声明了指针类型,所以只要告诉编译器ImportantClass一个类就够了。真正的类型信息 在userclass.cpp中提供。这种方式就是前置声明。以下是修改过的userclass.cpp文件:

通俗易懂----C++前置声明

通过这种方式消除了main.cpp对于ImportantClass的依赖。项目的依赖层次越多,前置声明的效果也就越明显。

 

enum前置声明

C++11中,enum类型也可以前置声明了。下面直接引用C++ Primer中的例子。

enum intValues : unsigned long long; //不限定作用域的,必须指明类型

enum class open_modes; //限定作用域的也可以指定,如果不指定则默认int

 

实际的枚举值可以在另外的cpp文件中另外定义。
 

上一篇:Linux安装


下一篇:新来的领导下令升级 MySQL 8.0,完美掉坑…