【问题标题】:GCC on Linux searching for a forward declared method in the wrong namespaceLinux 上的 GCC 在错误的命名空间中搜索前向声明的方法
【发布时间】:2018-12-11 09:56:03
【问题描述】:

考虑以下场景:

源.cpp

int add(int a, int b) { return a + b; } // function in global scope

头文件.h

namespace ns
{
    class A
    {
    public:
        void do()
        {
            ...
            ...
            method();
            ...
            ...
        }
    private:
        int method()
        {
            ...
            ...
            int add(int a, int b); // forward declaration
            auto result = add(5, 10); // function call
            ...
            ...
            // do something with result
        }
    };
}

Windows(MS 编译器) 上,上述操作按预期工作。

Linux (GCC) 上,它会导致链接器错误,其中方法 add() 被报告为 未定义的引用

而且,错误说明编译器试图在ns命名空间下寻找add(),但在全局命名空间中明确定义。

在链接前向声明的方法时,Linux 上的 GCC 的行为是否与 Windows 上的 MS 编译器不同?我该如何解决这个问题?

【问题讨论】:

    标签: c++11 gcc linker forward-declaration


    【解决方案1】:

    MS 编译器的名称查找在解析 在 ns::A::method 的正文中声明 int add(int a, int b)Source.cpp 中定义的函数的全局声明。该声明在命名空间内 ns 并且它应该声明的函数是int ns::add(int a, int b),它是 GCC(或clang)抱怨,没有定义。

    C++11 § 3.5 第 7 段:

    当一个具有链接的实体的块范围声明没有找到引用其他声明时, 那么该实体是最里面的封闭命名空间的成员。然而这样的声明并不 在其命名空间范围内引入成员名称。 [ 例子:

    namespace X {
        void p() {
            q(); // error: q not yet declared
            extern void q(); // q is a member of namespace X
        }
        ...
        ...
    
        void q() { /* ... */ } // definition of X::q
    }
    
    void q() { /* ... */ } // some other, unrelated q
    

    结束示例]

    你有两种选择:-

    • int add(int a, int b)的前向声明提升出命名空间 ns 进入全局命名空间 - 在 source.cpp 中定义的命名空间

    • int add(int a, int b)的定义包含在命名空间ns中:

    Source.cpp

    namespace ns {
        int add(int a, int b) { return a + b; }
    }
    

    【讨论】:

    • 所以 MS 的实现有误。你知道他们是否已经提出了一个错误吗?
    猜你喜欢
    • 2012-12-15
    • 2011-05-14
    • 2012-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-10
    相关资源
    最近更新 更多