| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> C++知识库 -> 实用经验 58 防止重复包含头文件 -> 正文阅读 |
|
[C++知识库]实用经验 58 防止重复包含头文件 |
头文件重复包含,是每个程序员都遇到过的问题。头文件重复包含,可能会导致的错误包括:变量重定义,类型重定义及其他一些莫名其妙的错误。现在我们就讨论如何避免这些问题。 假设,我们的工程中存在a.h,b.h及c.cpp等3个文件。其中b.h中包含了a.h,而c.cpp又包含了a.h和b.h两个文件。文件代码如下所示。
如果,你在VC++编译器中编译上述代码。在编译过程中,编译器会抛出“重复定义”错误。因为a.h被重复包含了2次。为了避免同一个文件被重复包含多次。C++提出了2种解决方案。他们是#ifndef方式和#pragman once方式。 方式1:
方式2:
1. #ifndef方式 这种实现方式,通过预处理实现唯一检查。预处理器首先测试__SOME_FILE_H__预处理器变量是否未定义。如果__SOME_FILE_H__未定义,那么#ifndef测试成功,跟在#ifndef 后面的所有行都被执行,直到发现 #endif。相反,如果__SOME_FILE_H__已定义,那么#ifndef 指示测试为假,该指示和#endif指示间的代码都被忽略。 为了保证头文件在给定的源文件中只处理过一次,我们首先检测#ifndef。第一次处理头文件时,测试会成功,因为__SOME_FILE_H__还未定义。下一条语句定义了__SOME_FILE_H__。那样的话,如果我们编译的文件恰好又一次包含了该头文件。#ifndef 指示会发现__SOME_FILE_H__已经定义,并且忽略该头文件的剩余部分。 头文件应该含有保护符,即使这些头文件不会被其他头文件包含。编写头文件保护符并不困难,而且如果头文件被包含多次,它可以避免难以理解的编译错误。 当没有两个头文件定义和使用同名的预处理器常量时,这个策略相当有效。当有两个文件使用同一个宏,这个策略就失效了。当遇到这种问题时,一般有两种解决方案。 方案1:可以为定义在头文件里的实体(如类)命名预处理器变量,来避免预处理器变量重名的问题。例如:一个程序只能含有一个名为Sales_item的类。通过使用类名来组成头文件和预处理器变量的名字,可以使得很可能只有一个文件将会使用该预处理器变量。 方案2:为了保证宏的唯一性,我们可以采用google提供的解决方案,在定义宏时,宏名基于其所在的项目源代码数的全路径命名。宏命名格式为:
最佳实践
2. #pragma once 这种方式一般又编译器提供,只要在头文件的最开始加入这条指令就能够保证头文件被编译一次#pragma once用来防止某个头文件被多次include,#ifndef方式用来防止某个宏被多次定义。 #pragma once是编译相关,就是说这个编译系统上能用,但在其他编译系统不一定可以,也就是说移植性差,不过现在基本上已经是每个编译器都有这个定义了。 #ifndef,#define,#endif这是C++语言相关的,是C++语言中的宏定义,通过宏定义避免文件多次编译。所以在所有支持C++语言的编译器上都是有效的,如果写的程序要跨平台,最好使用这种方式。 小心陷阱
3. #pragma once与 #ifndef的区别 #ifndef的方式依赖于宏名字不能冲突,这不光可以保证同一个文件不会被包含多次,也能保证内容完全相同的两个文件不会被不小心同时包含。当然,缺点就是如果不同头文件的宏名不小心“撞车”,可能就会导致头文件明明存在,编译器却硬说找不到声明的窘况。 #pragma once则由编译器提供保证:同一个文件不会被包含多次。注意这里所说的“同一个文件”是指物理上的一个文件,而不是指内容相同的两个文件。带来的好处是,你不必再费劲想个宏名了,当然也就不会出现宏名碰撞引发的奇怪问题。对应的缺点就是如果某个头文件有多份拷贝,本方法不能保证他们不被重复包含。当然,相比宏名碰撞引发的“找不到声明”的问题,重复包含更容易被发现并修正。 请谨记
|
|
C++知识库 最新文章 |
【C++】友元、嵌套类、异常、RTTI、类型转换 |
通讯录的思路与实现(C语言) |
C++PrimerPlus 第七章 函数-C++的编程模块( |
Problem C: 算法9-9~9-12:平衡二叉树的基本 |
MSVC C++ UTF-8编程 |
C++进阶 多态原理 |
简单string类c++实现 |
我的年度总结 |
【C语言】以深厚地基筑伟岸高楼-基础篇(六 |
c语言常见错误合集 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年3日历 | -2025/3/4 8:33:35- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |