考虑以下场景:
来源.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编译器不同?如何解决此问题?
MS编译器的名称查找在解决将int add(int a, int b)
在ns::A::method
的主体内声明为CCD_ 6中定义的函数的全局声明。该声明在命名空间中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
:中
源.cpp
namespace ns {
int add(int a, int b) { return a + b; }
}