关于头文件

提示:文章

文章目录

前言

前期疑问:
本文目标:


一、背景

2024年9月10日18:50:11

在看代码规范的时候又看到头文件相关的知识点,今天又再次整理一下,对头文件的使用又加深了理解。以前会莫名其妙报些告警,现在遇到应该会好处理了。

上述表述等于是将头文件中哪些可以定义哪些不能定义整理了一下
之前整理的文章是这一篇关于头文件,这次整理时也参考了这篇文章,而且再次看这篇文章的时候有了新的发现。真不错!**

二、

2.1 constexpr定义的变量是否可以放在头文件中

想把constexpr int STATISTICS_MAP_MAX_SIZE = 24 * 6 * 200;放在头文件中,就在疑惑能不能将const放在头文件中

1.在头文件中定义const类型的非static变量,在link时不会报错,这是因为const型的变量在complie时已经转换为常量,每个obj模块里有一个相同内容的常量,并不会有变量名冲突发生。

2.在头文件定义非const类型时,link时报错,这是因为这样相当于在每个包含该头文件的cc文件的全局域定义了一个名字相同的全局变量,虽然在complie时由于分开编译,不会产生错误,但是在link时,将会发生变量名冲突。

3.在头文件中使用extern 声明一个全局变量时可以的,而且是全局变量使用的推荐做法,前提是声明的这个全局变量,已经在一个cc文件,且只在一个cc文件中定义。

4.在头文件中定义的一个static变量,对于包含该头文件的所有源文件,实质上在每个源文件内定义了一个同名的static变量,他们仅为该源文件的全局变量而非全程序的全局变量。实际上在编译过程中,会为其每个obj模块中编译产生不同的名字,所以在link时候不会报错。但这样相当于在每个obj模块中有一个的static变量,它实际上是独立在每个obj模块中的文件级全局变量,不是全程序域的全局变量。

所以,在头文件中,最好只声明而不定义,定义也仅仅定义const型变量

来源:C语言头文件里可不可以定义变量

2.2 结构体是否可以定义在头文件中

总之,结构体的定义位置根据项目的需要和结构体的使用范围来决定。如果需要在多个源文件中共享结构体定义,则应该放在头文件中;如果仅在一个源文件中使用,则可以直接在源文件中定义。

今天重新看了下之前的一篇文章,关于头文件,这篇文章之前是拷贝的其他文章,有缺失,但是今天看了下发现了一个知识点,即之前我在疑问,结构体能否写在头文件中,今天看到那篇文章写到。不能写在头文件中的是变量和函数。

当然结构体可以定义在头文件中,但是如果只有一个源文件使用,就可以写在源文件中。

关于头文件不能定义函数和变量,有几个例外,看到一个文章说的比较好:

参考《C++ Primer中文版》第四版 人民邮电出版社 P58:

因为头文件包含在多个源文件中,所以不应该含有变量或函数的定义。

对于头文件不应该含有定义这一规则,有三个例外。头文件可以定义类、值在编译时就已经知道的const对象和inline函数。这些实体可在多个源文件中定义,只要每个源文件中的定义是相同的。

在头文件中定义这些实体,是因为编译器需要它们的定义(不只是声明)来产生代码

类定义含类作用域内的函数与变量定义,也就是成员函数与数据成员。

1、内成员函数如果隐式内联了,当然没有问题,可以放在头文件中。否则,如果显示内联,可以放在头文件中。如若不然,放在头文件中可能引起重复定义。

2、数据成员:静态成员定义放在头文件中,可能会引起重复定义。非静态数据成员定义在类实例化的时候,才定义。

从根本上分析的话,还得从链接属性上分析。

上述表述等于是将头文件中哪些可以定义哪些不能定义整理了一下

三、头文件相互引用相关

3.1 禁止头文件相互引用

看代码规范,提到禁止头文件相互引用。之前好像遇到过头文件相互依赖,当时肯定很懵逼啊,而且在实际开发中遇到就很捉急。现在就此深化理解一下。

因为当时出现头文件循环依赖的时候并没有专门去记录。只是回退了操作。

现在参考规范,写了个循环依赖的示例。

代码如下:

// Foo.h文件

// Foo.h文件
#ifndef TESTPROJ_LOCAL_WITHOUT_LIBRARY_FOO_H
#define TESTPROJ_LOCAL_WITHOUT_LIBRARY_FOO_H

#include "Container.h"

class Foo {
    Container* container;
};

#endif //TESTPROJ_LOCAL_WITHOUT_LIBRARY_FOO_H

// Conatiner.h文件

// Conatiner.h文件
#ifndef TESTPROJ_LOCAL_WITHOUT_LIBRARY_CONTAINER_H
#define TESTPROJ_LOCAL_WITHOUT_LIBRARY_CONTAINER_H

#include <iostream>
#include <map>
#include "Foo.h"

class Container {
    std::map<std::string, Foo> table;
};

#endif //TESTPROJ_LOCAL_WITHOUT_LIBRARY_CONTAINER_H

// main.cpp文件

#include "Foo.h"
#include "Container.h"

int main()
{
    Foo foo;
    Container container;
	std::cout << "program ok" << std::endl;
    return 0;
}

上述代码创建在一个工程中,会报错如下

D:/AppData/CLion/testProj_local_without_library/headFileInclude/Container.h:14:27: error: 'Foo' was not declared in this scope
   14 |     std::map<std::string, Foo> table;
      |                           ^~~
D:/AppData/CLion/testProj_local_without_library/headFileInclude/Container.h:14:30: error: template argument 2 is invalid

对于这个错误我一开始是不好理解的,查了资料

循环依赖是一种设计上的问题,需要避免。如果发生了循环依赖,编译器可能会报错或警告,并阻止代码的编译通过。解决循环依赖问题的最佳方法是重新设计代码结构,以消除循环依赖。

感觉编译器是禁止编译通过。、

这个问题怎么解决呢?使用类前置声明。

3.2 c++类前置声明

修改成下述形式:

// Foo.h文件

// Foo.h文件
#ifndef TESTPROJ_LOCAL_WITHOUT_LIBRARY_FOO_H
#define TESTPROJ_LOCAL_WITHOUT_LIBRARY_FOO_H

#include "Container.h"

class Foo {
    Container* container;
};

#endif //TESTPROJ_LOCAL_WITHOUT_LIBRARY_FOO_H

// Conatiner.h文件

// Conatiner.h文件
#ifndef TESTPROJ_LOCAL_WITHOUT_LIBRARY_CONTAINER_H
#define TESTPROJ_LOCAL_WITHOUT_LIBRARY_CONTAINER_H

#include <iostream>
#include <map>
//#include "Foo.h"

class Foo;

class Container {
    std::map<std::string, Foo> table;
};

#endif //TESTPROJ_LOCAL_WITHOUT_LIBRARY_CONTAINER_H

// main.cpp文件

#include "Foo.h"
#include "Container.h"

int main()
{
    Foo foo;
    Container container;
    std::cout << "program ok" << std::endl;
    return 0;
}

就可以成功编译程序并执行

然后突然意识到这是对于c++代码类的解决办法。如果是c语言循环依赖该怎么解决?

暂时先不管这个。先解决上述类的问题。

我想到的一个就是重新设计代码。


总结

未完待续

### 回答1: 如果您在编译STM32代码时遇到了头文件路径未添加的错误,可以按照以下步骤解决: 1. 确认您的头文件是否位于正确的路径下,例如在您的项目文件夹中的"inc"文件夹内。 2. 在您的工程设置中,确保您已经添加了正确的头文件路径。这通常可以在IDE的“工程设置”或“项目属性”菜单中找到。如果您使用的是CubeMX,则可以在“Project Manager”中找到“Code Generator”选项卡,然后在“Advanced Settings”中添加您的头文件路径。 3. 如果您已经添加了正确的路径,但仍然遇到了该错误,请确保您的头文件名称拼写正确,大小写也正确。 4. 最后,您可以尝试在代码中直接使用相对路径来包含头文件。例如,如果您的头文件在“inc”文件夹中,您可以使用“#include "../inc/header.h"”来包含它。 如果您的问题仍然无法解决,请参考您的IDE或编译器的文档,或向相关论坛或社区寻求帮助。 ### 回答2: 在使用STM32开发板进行编程时,经常会遇到头文件路径未添加的错误问题,导致编译无法找到相应的头文件。这种错误通常出现在使用了自定义的头文件时。 当我们在工程中包含其他文件或库时,需要在代码中添加相应的头文件路径,以便编译器能够正确地找到这些文件。 解决这个问题的方法有以下几种: 1. 修改头文件路径:在使用IDE开发环境时,可以通过打开项目属性或构建设置等设置界面,将头文件路径添加到项目的搜索路径中。这样,编译器就可以在这些路径中查找需要的头文件。 2. 使用相对路径:如果头文件与代码文件在同一目录下,可以使用相对路径来引用头文件。例如,如果需要引用一个名为"header.h"的头文件,可以在代码中使用"include "header.h""来包含该头文件。 3. 使用绝对路径:如果头文件不在当前工程所在目录下,可以使用绝对路径来引用头文件。在代码中使用完整路径名,例如"include "C:/path/to/header.h""。 4. 检查头文件是否存在:如果以上方法仍无法解决问题,需要检查头文件是否存在于指定的路径中。可能是由于文件名错误或路径错误导致编译器无法找到头文件。 在解决这类问题时,我们需要仔细查看错误信息,了解具体的错误原因。通常,编译器会指出缺少的头文件名称和具体路径。根据这些信息,可以逐步排查问题并采取相应的解决措施。 需要注意的是,正确引用头文件路径是编写良好代码的重要一环。正确添加头文件路径可以确保编译器能够正确找到所需的头文件,从而顺利完成编译和构建过程。 ### 回答3: 在STM32开发中,如果在编译时出现"cannot open source input file"的错误提示,通常是由于头文件路径没有添加正确导致的。 在编译C/C++程序时,编译器需要找到程序中所引用的头文件头文件路径告诉编译器在哪里找到这些头文件。 要解决这个问题,我们需要在编译器的设置中添加正确的头文件路径。 首先,打开项目的工程文件,找到编译器的设置选项。这些设置通常包含在一个makefile或者一个配置文件中。 接下来,找到编译器设置中的头文件搜索路径(Include Directories)选项。这个选项通常以"-I"开头,后面跟着头文件所在的路径。 确保这个路径是正确的,包含了所有需要的头文件路径。如果头文件位于项目文件夹内的子文件夹中,可以使用相对路径来指定。 另外,还可以使用绝对路径来指定头文件路径,这样可以确保编译器一定能够找到这些头文件。 完成以上设置后,重新编译项目,这个错误应该就会消失了。 总结而言,解决STM32关于头文件路径没有添加错误问题,需要在项目的编译器设置中添加正确的头文件搜索路径。确保路径正确、包含所有需要的头文件路径,重新编译即可解决问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值