#ifndef #define #endif #ifdef 避免重复引用
一:在什么阶段处理 ?
预处理 预处理 预处理
首先注意这四个头文件保护符
是在预处理阶段由系统默认的预处理器
(Linux操作系统上默认是cpp)来处理的。它们的含义如下:
#define XXX // 将XXX声明为一个预处理变量
#ifndef XXX // 当且仅当XXX没有被定义为"真"
#ifdef XXX // 当且仅当XXX被定义时为"真"
#endif // 遇到endif结束
二:怎么使用?
给个重复定义的例子如下所示:
A.h
class A {
public:
A() = default;
A(int i) {
id = i;
}
int id;
};
B.h
class A {
public:
A() = default;
A(int i) {
id = i;
}
int id;
};
main.cpp
#include<iostream>
#include"A.h"
#include"B.h"
int main(int argc,char *argv[])
{
A a(9);
std::cout << a.id << std::endl;
return 0;
}
编译报错如下所示:
它提示”class A”被重复定义了,既然它的处理过程是在预处理阶段,那我们可以gcc -E
生成预处理之后的文件看看。
$ g++ -E main.cpp -o main.i
看看main.i
的内容,发现果然class A的内容被引入了两份
。
在编译的时候就会报错(cc1是Linux下默认编译器):
三:怎么改?
很容易,使用头文件保护符就好了。使用套路如下所示:
#ifndef XXX //如果没有定义XXX
#define XXX //那就定义XXX,直到遇到endif
#endif //遇到endif表示结束定义
去修改我们的A.h
和B.h
如下所示:
之后再次预处理下看看:
发现class A
只有一份了吧!并且编译正常通过。
四:总结
其实这几个头文件保护符
应该作为我们的一种编程习惯,而不是在发生冲突的时候才使用。这样保证了我们工程的健壮。至于它们别的作用,条件编译等等,也是对这几个符号的属性不同的利用场景罢了,我就不赘述了。
#ifndef #define #endif #ifdef 避免重复引用的更多相关文章
- #ifndef #define #endif 防止头文件被重复引用
想必很多人都看过“头文件中的 #ifndef/#define/#endif 防止该头文件被重复引用”.但是是否能理解“被重复引用”是什么意思?是不能在不同的两个文件中使用include来包含这个头文件 ...
- ifndef/define/endif 和 #ifdef 、#if 作用和用法
为了能简单的看看某些linux内核源码,复习了一下c语音,今天汇总了一下关于宏定义的相关内容: 一.ifndef/define/endif用法: .h文件,如下: #ifndef XX_H #defi ...
- C++头文件为什么要加#ifndef #define #endif
#ifndef 在头文件中的作用 在一个大的软件工程里面,可能会有多个文件同时包含一个头文件,当这些文件编译链接成一个可执行文件时 ,就会出现大量“重定义”的错误.在头文件中实用#ifndef #de ...
- #ifndef#define#endif的用法
在网上看到了感觉作者总结得很好,作者辛苦了! #ifndef#define#endif的用法 文件中的#ifndef 头件的中的#ifndef,这是一个很关键的东西.比如你有两个C文件,这两个C文件都 ...
- #ifndef#define#endif的用法(整理)
[转] #ifndef#define#endif的用法(整理) 原作者:icwk 文件中的#ifndef 头件的中的#ifndef,这是一个很关键的东西.比如你有两个C文件,这两个C文件都in ...
- 头文件里面的ifndef /define/endif的作用
c,c++里面,头文件里面的ifndef /define/endif的作用 今天和宿舍同学讨论一个小程序,发现有点地方不大懂······ 是关于头文件里面的一些地方: 例如:要编写头文件test.h ...
- 转 #ifndef/#define/#endif使用详解
想必很多人都看过“头文件中的 #ifndef/#define/#endif 防止该头文件被重复引用”.但是是否能理解“被重复引用”是什么意思?是不能在不同的两个文件中使用include来包含这个头文件 ...
- 头文件为什么要加#ifndef #define #endif
#ifndef 在头文件中的作用 在一个大的软件工程里面,可能会有多个文件同时包含一个头文件,当这些文件编译链接成一个可执行文件时 ,就会出现大量“重定义”的错误.在头文件中实用#ifndef #de ...
- 头文件中的#ifndef/#define/#endif 的作用
在一个大的软件工程里面,可能会有多个文件同时包含一个头文件,当这些文件编译链接成一个可执行文件时,就会出现大量重定义的错误.在头文件中实用#ifndef #define #endif能避免头文件的重定 ...
随机推荐
- Docker系列(18)- 具名挂载和匿名挂载
容器数据卷挂载方式 容器的数据卷可以看成就是容器的挂载方式:一个宿主机有多个容器,多个容器挂载方式不同,因此宿主机就有多个卷 每一个挂载方式在宿主机上都有一个名称,即卷名 宿主机如何查看这些卷,对使用 ...
- JDK1.8源码(三)——java.lang.String类
一.概述 1.介绍 String是一个final类,不可被继承,代表不可变的字符序列,是一个类类型的变量.Java程序中的所有字符串字面量(如"abc")都作为此类的实例实现,&q ...
- python 建站教程
主端:安装nginx uwsgi django pymysql mysql安装mysql到http://repo.mysql.com/里面找 mysql57-community-release-el7 ...
- Kettle学习笔记(一)— 环境部署及运行
目录 Kettle学习笔记(一)-环境部署及运行 Kettle学习笔记(二)- 基本操作 kettle学习笔记(三)- 定时任务的脚本执行 Kettle学习笔记(四)- 总结 Kettle简介 Ket ...
- FastAPI(59)- 详解使用 OAuth2PasswordBearer + JWT 认证
JWT JSON Web Tokens 它是一个将 JSON 对象编码为密集且没有空格的长字符串的标准 使用 JWT token 和安全密码 hash 使应用程序真正安全 JWT 小栗子 eyJhbG ...
- MySQL8 根据某属性查询字段排名由自定义变量到rank()的变动
在mysql8 之前的版本,因为没有rank()方法的存在,所以在对字段进行排名时,使用的是自定义自变量的方法,比如: select id,name,@rank=@rank+1 as ranks fr ...
- 互联网公司作息表「GitHub 热点速览 v.21.42」
作者:HelloGitHub-小鱼干 检测一家公司是否值得一去,除了高薪之外,还有时薪的算法.即便是同样的时薪,在一家能随时摸鱼的公司,岂不是人生快事.WorkingTime 便是上周很火的互联网作息 ...
- mysql order by语句流程是怎么样的
order by流程是怎么样的 注意点: select id, name,age,city from t1 where city='杭州' order by age limit 1000; order ...
- 初探JavaScript PDF blob转换为Word docx方法
PDF转WORD为什么是历史难题 PDF 转Word 是一个非常非常普遍的需求,可谓人人忌危,为什么如此普遍的需求,却如此难行呢,还得看为什么会有这样的一个需求: PDF文档遵循iOS32000的规范 ...
- 网络通信IO的演变过程(一)(一个门外汉的理解)
以前从来不懂IO的底层,只知道一个大概,就是输入输出的管道怼到一起,然后就可以传输数据了. 最近看了周志垒老师的公开课后,醍醐灌顶. 所以做一个简单的记录. 0 计算机组成原理相关 0.1. 计算机的 ...