我在重新安排我的C ++项目时遇到了这个问题,以避免文件名和命名空间冲突。
所以,我在一个简单的项目上复制了这个问题,以下是它的文件。
文件client.hpp: -
#ifndef CLIENT_HPP
#define CLIENT_HPP
namespace work { namespace test {
int get_age(){
return 33;
}
}
}
#endif
文件work.hpp: -
#ifndef WORK_HPP
#define WORK_HPP
#include <iostream>
#include "client.hpp"
namespace work { namespace test {
class NewWork{
public:
NewWork(std::string name);
std::string getName();
int getAge();
private:
std::string _name;
};
}
}
#endif
文件work.cpp: -
#include "work.hpp"
using namespace work::test;
NewWork::NewWork(std::string name) : _name(name) {}
std::string NewWork::getName() { return _name; }
int NewWork::getAge() { return get_age(); }
文件main_fun.cpp: -
#include "work.hpp"
using namespace work::test;
int main(int argc, char **argv){
NewWork w = NewWork("hari");
std::cout << "Name: " << w.getName()
<< " Age: " << w.getAge()
<< std::endl;
return 0;
}
文件CMakeLists.txt: -
cmake_minimum_required(VERSION 2.6)
project(work)
set(PROJECT_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set ( SRC_FILES
${PROJECT_DIR}/work.cpp
${PROJECT_DIR}/main_fun.cpp
)
include_directories(${PROJECT_DIR})
add_executable(${PROJECT_NAME} ${SRC_FILES})
因此,在构建此项时,我收到以下错误: -
Linking CXX executable work
CMakeFiles/work.dir/main_fun.cpp.o: In function `work::test::get_age()':
main_fun.cpp:(.text+0x0): multiple definition of `work::test::get_age()'
CMakeFiles/work.dir/work.cpp.o:work.cpp:(.text+0x0): first defined here
collect2: error: ld returned 1 exit status
make[2]: *** [work] Error 1
make[1]: *** [CMakeFiles/work.dir/all] Error 2
make: *** [all] Error 2
我发现的一件事是,如果我让函数work :: test :: get_age()到static
那么它编译和链接没有任何问题。我不明白为什么它适用于static
。
头文件的保护是正确的,所以不能多次包含它,或者我在这里遗漏任何东西?
谢谢,
Haridas N。
答案 0 :(得分:4)
您在标头中定义了get_age
。这意味着它会被每个#include
中的.cpp
复制到每个翻译单元。
在命名空间范围内标记static
时,会使每个副本“本地”到该翻译单元,因此不会发生冲突。
如果你将它标记为inline
,你会向编译器和链接器承诺每个翻译单元中的定义是相同的(我们可以看到它),因此多个副本将被神奇地卷入只有一个。
但是,正确的方法是在标题中声明,并在一个源文件中 define ,就像使用类的成员函数一样。
答案 1 :(得分:3)
当您加入client.hpp
文件时,get_age
功能已定义。如果您将头文件包含在多个源文件中,那么您将拥有此函数的多个定义。
你应该做的是声明头文件中的函数,然后在一个源文件中定义它。
所以在头文件中只做
namespace work {
namespace test {
int get_age();
}
}
在源文件中创建定义
int work::test::get_age() {
...
}
答案 2 :(得分:1)
声明函数inline
(正如您在标题中提供的实现...)