在命名空间内定义函数时引发链接器错误? [复制]

Posted

技术标签:

【中文标题】在命名空间内定义函数时引发链接器错误? [复制]【英文标题】:Linker errors thrown when defining a function inside of a namespace? [duplicate] 【发布时间】:2020-07-25 21:37:50 【问题描述】:

为什么我无法在 .cpp 文件(不是 main.cpp)的命名空间内定义函数?

例如,假设我想将我的代码分成 2 个不同的文件,main.cpp,然后是 lib.cpp(带有关联的 lib.h 文件)。

以下设置会引发链接器错误: lib.h:

#ifndef LIB_H_
#define LIB_H_
namespace a
void foo();

#endif

lib.cpp:

#include "lib.h"
using namespace a;
void foo()
std::cout<<"Hello World!"<<std::endl;

main.cpp:

#include "lib.h"
int main()
a::foo();
return 0;

不过,我能想到的几乎任何其他变体都有效。

在 lib.h 文件而不是 lib.cpp 中定义函数可以工作 删除命名空间有效 保留命名空间,而是将 foo 作为公共方法 我在主函数中实例化然后调用的类,工作

在我看来这可能是一种约定俗成的事情?鼓励人们使用类或在 .h 文件中完全定义函数?我得到的链接器错误是“undefined symbols(a::foo()) for architecture...”

为什么会这样? 我在使用 CLion 的 Mac 上。

【问题讨论】:

你已经声明了一个函数a::foo,但是你定义了一个全局命名空间函数::foo。您的声明应在namespace 块内,或声明为void a::foo() using namespace 声明不足。 【参考方案1】:

using namespace a; 不是在命名空间内定义函数的方法。

语法与声明相同:namespace a ...

#include "lib.h"
namespace a 
    void foo()
        std::cout<<"Hello World!"<<std::endl;
    

更多详情请参考:Namespaces。

【讨论】:

只是澄清一下-即使我在 lib.h 中使用命名空间 a... 声明了该函数,我也无法使用“使用命名空间”语法来定义它? 正确。 “使用命名空间”语法始终是只读的。【参考方案2】:

你必须添加

target_link_libraries(<name of your executable> <name of your library>)

将库符号和函数链接到您的可执行文件。

您正在全局命名空间中定义函数。

lib.cpp中这样定义你的函数

void a::foo() 
    ...

见下面代码中的cmets

lib.h

#ifndef LIB_H_ 
#define LIB_H_ 
namespace a 
    void foo(); // declaring a::foo()
 
#endif

lib.cpp

#include "lib.h" 
using namespace a; 
void foo() // defining ::foo() and thats why calling foo() without namespace a works
    std::cout<<"Hello World!"<<std::endl; 

【讨论】:

谢谢!但是我的 cmake 已经在使用 add_library() 和 target_link_libraries(),它们似乎也能正常工作,因为我可以在 .h 文件中声明类并在我的 .cpp 文件中定义它们,即使它们是命名空间

以上是关于在命名空间内定义函数时引发链接器错误? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

分离式编译时 链接器工具错误 (一个变量被定义一次或多次)

名称空间作用域闭包装饰器迭代器生成器

自调函数的写法:

链接器在命名空间中找不到函数定义

有没有办法在创建项目时设置项目的默认命名空间?

成员函数内定义static变量