CPP_头文件互相包含

CPP_头文件互相包含

[!Error]+
编写 C++ 代码时偶尔会遇到两个类需要相互引用的情况,如果在 h 文件中相互包含会导致 “has not been declared” 等声明问题,此时需要使用前置声明的方式来解决该问题

Code Example

以一个实际场景为例:假设有工具类 Search Helper 提供一系列搜索功能,还有另一个 ObjectAttr 定义一系列操作对象的属性,在 ObjectAttr 中需要引用 SearchHelper 提供的某个基础函数,而 SearchHelper 中部分针对 ObjectAttr 设计的某些功能则需要将 ObjectAttr 中的类作为入参,此时我们可能会在 h 文件中相互引用;

在 obj_definition.h 中有 GetSelfNearObj 函数,其过程中需要调用 search_helper 中的 GetDistObj 函数进行辅助运算

1
2
3
4
5
6
7
8
9
10
11
#include "util/search_helper.h"
namespace object_info{
class ObjectAttr{
public:
LocationType location;
int ObjId;
int NearObjId;
private:
void GetSelfNearObj();
};
}

在 search_helper.h 中有以下函数定义

1
2
3
4
5
6
7
#include "base/obj_definition.h"
namespace search_helper{
class SearchHelper{
public:
int GetDistObj(const object_info::ObjectAttr & obj1, const object_info::ObjectAttr & obj2);
};
}

这种情况下编译会出现未定义,未声明,not a type 之类缺少类型说明符的错误。

1
error: ... has not been declared

Fix & Analysis

上述错误是由于两个文件构成了循环依赖,类 SearchHelper 依赖于 ObjectAttrObjectAttr 又依赖于 SearchHelper;因此编译器会报错导致无法通过编译;

在这种情况下,可以通过前向声明的方式来解决这种问题,即不去进行循环引用,在search_helper 中不 #include obj_definition.h,但是对需要的 ObjectAttr 进行一个空声明,然后在 .cpp 中 #include obj_definition.h 具体如下,将 H 文件修改为;

1
2
3
4
5
6
7
8
9
10
namespace objct_info{
class ObjectAttr;
}

namespace search_helper{
class SearchHelper{
public:
int GetDistObj(const object_info::ObjectAttr & obj1, const object_info::ObjectAttr & obj2);
};
}

在对应的 .cpp 文件中添加对 obj_definition 的包含,这样在编译过程中,ObjectAttr 会被自动链接到正确的定义;

1
2
3
4
#include "base/obj_definition.h"

// origin cpp file below...
// ...

上述例子展示了不同命名空间下的情况,这里秉持的原则就是不同文件中对类的前置声明要保持一致,无论是命名空间、参数、类型等,在同一个命名空间中的情况要更简单,可以以此类推,这里不再赘述;

Reference

  1. c++ 头文件互相包含问题
  2. c++ 类声明 类前置声明范例

Cherno的cpp教程笔记

Cherno的cpp教程笔记

this notebook is based on Cherno‘s Video Class in YouTube;if there is sth get confused,I can recheck the video which talk about it, or just google it.

  • this is not totally for newbie, so some basic information we should search it
  • And this is a important websize to tell us basic info about C++.

C++的常见数据类型和操作

C++的常见数据类型和操作

主要介绍一些常用数据类型的一些method,区别还有一些特殊的定义;

priority_queue 默认是大顶堆,great的话是小顶堆,less的话是大顶堆,自定义的话不知道是不是一致的

set默认top是小顶,这个大小我就不知道了,自定义的话,好像和我想得是一致的

所有的动态容器都是存放在heap上的,像是什么Vector,String,unordered_map之类的

指定精度的输出和计算

在腾讯的笔试中出现的需要指定精度和指定的计算精度的分析,在使用常数的时候一定要使用.0去修正一个方法。

Vector 动态数组

Vector中的一些常用的函数,方法,以及一些属性介绍和辨析

emplace_back & push_back(在末尾添加元素)

empalce_back直接在数组的末尾进行构造,而push_back借助于构造的临时变量再将其加入数组末尾,所以在一些操作中empalce_back对于空间时间的效率是会更高的,但是如果我们有重复构筑的数据的话,可能就需要使用push_back

要注意实际上vector中并没有append的方法。