从全局命名空间中引用某个东西?

4

这真的很琐碎,但我遇到了一个意外的错误。

我有一些代码位于命名空间中。

下面是一些伪代码,表示我的代码结构:

namespace A {
    void init() {
        initialize_kitchen_sink();
    }
    #include "operations.h" // declares shake_and_bake()
    void foo() {            
        shake_and_bake();
    }
    void cleanup() {
        // do nothin' cuz i'm a slob
    }
}

错误:

undefined reference to `A::shake_and_bake`

2
operations.h 文件中的所有内容都在命名空间 A 中声明。如果您在另一个文件中包含 operations.h 文件,但在不同的命名空间(例如全局)中,则这些将是完全不同的声明。请注意,#include 是预处理器的一部分,并且在任何语言结构完成之前就已经执行了其操作。 - Martin York
2个回答

7
原来将#include移出命名空间即可解决问题。
这样一来,包含文件会将operations.h中的所有函数声明放到A命名空间中。然后它会徒劳地搜索实现部分。
我认为,与其删除整篇文章,还不如把它留下来,因为可能有其他人遇到类似问题时可以受益于此。

最好将包含文件放在源文件的顶部,而不是在您首次需要逻辑的中间位置。 - J T
我还没有看到任何不将 includes 放在顶部的合适理由。尽管有时我仍会弄错,例如如果我将单元测试放在底部,#include "unittest++.h" 可能会出现在文件末尾,在所有单元测试宏之前。所以这似乎可以正常工作,但可能也是不好的形式。 - Steven Lu

6
为了准确回答你的问题,你可以使用 :: 作为第一个语句来引用全局命名空间中的某个内容,例如:
 void foo() {            
        ::shake_and_bake();
    }

当然,对于这种特殊情况,你的答案是正确的。

我不知道你可以这样做。这种情况只有在全局命名空间和当前命名空间中都声明了相同名称的东西时才有用吗? - Steven Lu
这也是我理解的方式。然而,我知道像 gtest(Google 单元测试框架)这样的框架严重依赖它,所以有些情况下你别无选择!Koenig 查找有时可能会很复杂 :) - Dinaiz
看自己几年前提出的问题并仍然学到新东西是很有趣的。Koenig Lookup很酷,我已经使用它一段时间了。 - Steven Lu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接