#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.hB.h如下所示:
这里写图片描述

之后再次预处理下看看:

这里写图片描述

发现class A只有一份了吧!并且编译正常通过。

四:总结

其实这几个头文件保护符应该作为我们的一种编程习惯,而不是在发生冲突的时候才使用。这样保证了我们工程的健壮。至于它们别的作用,条件编译等等,也是对这几个符号的属性不同的利用场景罢了,我就不赘述了。

posted on 2016-12-07 00:36  杨博东的博客  阅读(50)  评论(0编辑  收藏  举报

导航