大家知道,我们写.h文件时,通常会加上防卫式声明,有以下两种方式:

1. 宏定义

1
2
3
4
#ifndef _FILENAME_
#define _FILENAME_
//...
#endif

2. 编译器指令

1
#pragma once

  

但是,为什么头文件中需要添加这种防卫式声明呢?如果没有这样的声明,会出现怎样的问题。这里,先看一个例子。

-- "Car.h",代码如下(并没有添加防卫式声明):

1
2
3
4
5
// Car.h
class Car
{
// ...
};

-- "Person.h",代码如下(包含了Car.h文件):

1
2
3
4
5
6
7
// Person.h
#include "Car.h"
class Person
{
public:
    Car car;
};

-- 在"main.cpp"中,我们同时include两个头文件:

1
2
3
4
5
6
// main.cpp
#include "Car.h"
#include "Person.h"
int main(int argc, const char * argv[]) <br>{
    Person p;
}

此时,我们会发现编译出错:Redefinition of 'Car'.

可是为什么会出现这样的情况呢?

我们需要知道,在预编译阶段,编译器会把.h文件展开,即main.cpp中的代码可以看做是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Car
{
    // ...
};
 
class Car
{
    // ...
};
 
class Person
{
public:
    Car car;
};
 
int main(int argc, const char * argv[]) {
    Person p;
}

所以,我们可以知道防卫式声明的作用是:防止由于同一个头文件被包含多次,而导致了重复定义。

在这两种声明方式中:

  #ifndef 依赖于宏定义名,当宏已经定义时,#endif之前的代码就会被忽略,但是这里需要注意宏命名重名的问题;

  #pragma once 只能保证同一个文件不会被编译多次,但是当两个不同的文件内容相同时,仍然会出错。而且这是微软提供的编译器命令,当代码需要跨平台时,需要使用宏定义方式。

https://www.cnblogs.com/xyq10612/p/5910933.html

[C++]关于头文件中的防卫式声明的更多相关文章

  1. C++ 多文件编译简述:头文件、链接性、声明与定义

    目录 Commen Sense 头文件 链接性 static 与链接性控制 extern 与外部链接性 Reference Commen Sense C++ 在编译时对每个翻译单元(Translati ...

  2. C++-模板的声明和实现为何要放在头文件中

    源: http://blog.csdn.net/lqk1985/archive/2008/10/24/3136364.aspx 如何组织编写模板程序 发表日期: 1/21/2003 12:28:58 ...

  3. C ++模板的声明和实现为何要放在头文件中?

    源: http://blog.csdn.net/lqk1985/archive/2008/10/24/3136364.aspx 如何组织编写模板程序 发表日期: 1/21/2003 12:28:58 ...

  4. vs2022+resharper创建模板——实现在新建文件的时候自动生成防卫式声明和自定义语句

    在网上找了很久如何让visual studio新建文件的时候自动生成注释和防卫式声明,虽然防卫式声明可以用#proga once替代,但是在clion里可以自动生成vs里面没法自动生成还是觉得难受,于 ...

  5. cctype头文件中的一些内容

    1. string 标准库 1.1初始化 string s1; 默认构造函数s1为空 string s2(s1); 将s2初始化为s1的一个副本 string s3(“value”); 将s3初始化为 ...

  6. Effective Objective-C 2.0 — 第二条:类的头文件中尽量少引入其他头文件

    第二条:类的头文件中尽量少引入其他头文件 使用向前声明(forward declaring) @class EOCEmployer 1, 将引入头文件的实际尽量延后,只在确有需要时才引入,这样就可以减 ...

  7. c语言头文件中定义全局变量的问题

    c语言头文件中定义全局变量的问题 (转http://www.cnblogs.com/Sorean/) 先说一下,全局变量只能定义在 函数里面,任意函数,其他函数在使用的时候用extern声明.千万不要 ...

  8. 将inline、template声明和定义在头文件中

    如果要在要在源文件(a.cpp)中内联的展开一个函数(fun),则该源文件(a.cpp)中必须包含此函数(fun)的定义.如果要在多个文件中内联的展开fun,则在所有的源文件中都必须包含fun的定义. ...

  9. 头文件中的#ifndef/#define/#endif 的作用

    在一个大的软件工程里面,可能会有多个文件同时包含一个头文件,当这些文件编译链接成一个可执行文件时,就会出现大量重定义的错误.在头文件中实用#ifndef #define #endif能避免头文件的重定 ...

随机推荐

  1. git命令行删除远程分支

    先查看远程分支 git branch -r 使用下面两条命令来删除远程分支 git branch -r -d origin/branch-name git push origin :branch-na ...

  2. android4.3 蓝牙BLE编程

    一.蓝牙4.0简介 蓝牙4.0标准包含两个蓝牙标准,准确的说,是一个双模的标准,它包含传统蓝牙部分(也有称之为经典蓝牙Classic Bluetooth)和低功耗蓝牙部分(Bluetooth Low ...

  3. android中样式和自定义button样式

    1)自定义button样式 一.采用图片方式 首先新建Android XML文件,类型选Drawable,根结点选selector,自定义一个文件名. 随后,开发环境自动在新建的文件里加了select ...

  4. 基于sys文件系统的LED驱动的移植【原创】

    基于RK3188平台LED驱动程序的移植的移植.如有不正确之处,欢迎大家指点. 本文的LED驱动程序不是通过打开设备节点来访问和控制LED的,是通过sys文件系统来控制LED. 板子上有四盏灯以及对应 ...

  5. HDU2829 Lawrence —— 斜率优化DP

    题目链接:https://vjudge.net/problem/HDU-2829 Lawrence Time Limit: 2000/1000 MS (Java/Others)    Memory L ...

  6. Technocup 2017 - Elimination Round 2 C. Road to Cinema —— 二分

    题目链接:http://codeforces.com/problemset/problem/729/C C. Road to Cinema time limit per test 1 second m ...

  7. Spring Boot2.0之 整合Zookeeper集群

    普通的连接: pom: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://w ...

  8. HTML标题和段落

    HTML标题 通过<h1> - <h6> 等标签进行定义 <h1>一标题</h1> <h2>二标题</h2> <h3> ...

  9. XML与TreeView

    1.treeview代码书写 private void Form1_Load(object sender, EventArgs e) { //代码为TreeView添加子项 treeView1.Con ...

  10. Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。

    从浏览器中创建 XMLHttpRequests 从 node.js 创建 http 请求 支持 Promise API 拦截请求和响应 转换请求数据和响应数据 取消请求 自动转换 JSON 数据 客户 ...