为什么c ++命名空间内的定义在命名空间之外工作?

时间:2014-12-28 14:44:11

标签: c++ namespaces

如果我在命名空间中使用某些宏定义,那么为什么它们应该在命名空间之外工作?检查此代码,例如:

#include <bits/stdc++.h>

namespace foo {
    #define a x*2

    int f(int x) {
        return a;
    }
}

int main() {
    int a = 50;
    std::cout << a << endl;

    std::cout << foo::f(4) << endl;

    return 0;
}

这里我从未使用命名空间foo编写过。但是仍然没有编译这段代码,因为当尝试声明int a时,它会受到先前定义的a的干扰。但为什么会这样呢?

4 个答案:

答案 0 :(得分:6)

  

&#34; ...当尝试声明int a时,它会受到先前定义的a的干扰。但为什么会这样呢?&#34;

#define语句由c / c ++预处理器解释,它没有命名空间(或任何其他c ++语言结构)的概念。

如果要限制定义的范围,请使用#undef指令:

namespace foo {
    #define a x*2

    int f(int x) {
        return a;
    }
    #undef a
 // ^^^^^^^^
}

答案 1 :(得分:4)

预处理器不知道任何高级语言功能,例如命名空间或作用域。它只查找以#开头的行,然后进行简单的文本替换。这就是为什么在{+ 1}}或文件保护中使用预处理器在C ++中很危险的一个原因。

答案 2 :(得分:3)

#define不尊重任何C ++范围。没有"local" #define这样的东西。它会一直有效,直到#undef-ed

namespace foo {
    #define a x*2

    int f(int x) {
        return a;
    }
    #undef a              <<<<<<<<<<<<<<<<<<<<<
}

答案 3 :(得分:1)

C预处理器几乎就是它自己的语言。它首先执行。宏创建传递给实际C / C ++编译器的代码。无论什么时候使用宏,都要记住,宏会胜过一切,甚至是花括号。只有另一个预处理程序指令(如#undef)可以停止宏。

BTW,您甚至可以在任何文本文件上单独使用C预处理器。