此问题在此处已有答案:
C++ undefined references to functions in namespace(2个答案)
四个月前关门了。
在我正在处理的项目中,我遇到了一个问题,我得到了以下错误:
[ 97%] Linking CXX executable Test_formatters
CMakeFiles/Test_formatters.dir/formatters.cpp.o: In function `FormatterTests::JsonFormattter::test_method()':
formatters.cpp:(.text+0xa9e7): undefined reference to `core::log::make_formatter(core::log::FormatterType)'
collect2: error: ld returned 1 exit status
core/log/test/CMakeFiles/Test_formatters.dir/build.make:104: recipe for target 'core/log/test/Test_formatters' failed
make[2]: *** [core/log/test/Test_formatters] Error 1
CMakeFiles/Makefile2:504: recipe for target 'core/log/test/CMakeFiles/Test_formatters.dir/all' failed
make[1]: *** [core/log/test/CMakeFiles/Test_formatters.dir/all] Error 2
Makefile:135: recipe for target 'all' failed
make: *** [all] Error 2
这个函数是一个名为distro_core_log_static的函数库的一部分。下面是为这个函数库创建测试目标的cmake,这也是这个错误的来源:
ADD_DEFINITIONS(-DBOOST_TEST_DYN_LINK)
set(DEPENDENCIES
distro_core_log_static
${Boost_FILESYSTEM_LIBRARY}
${Boost_SYSTEM_LIBRARY}
${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
# formatters
add_executable(Test_formatters formatters.cpp)
target_link_libraries(Test_formatters PUBLIC ${DEPENDENCIES})
特别奇怪的是,我在日志库内部使用了这个据说未定义的方法,却没有得到这样的错误。下面是这个目录结构:
enter image description here
最后,您还可以看到该方法声明为:
namespace core
{
namespace log
{
class Formatter;
enum class FormatterType
{
invalid = -1,
json
}; // enum class FormatterType
// Factory method for log formatters
Formatter* make_formatter(FormatterType type);
// Convert the provided FormatterType to a string representation
std::string formatter_type_to_string(FormatterType type);
// Convert the provided FormatterType string to a FormatterType
FormatterType string_to_formatter_type(const std::string& formatter_type_str);
// String representations
static constexpr const char* const FORMATTER_INVALID_STR = "invalid";
static constexpr const char* const JSON_FORMATTER_STR = "json";
} // namespace log
} // namespace core
和定义:
#include "FormatterFactory.hpp"
#include "Formatter.hpp"
#include "JsonFormatter.hpp"
using namespace core::log;
// Factory method for log formatters
Formatter* make_formatter(FormatterType type)
{
switch (type)
{
case FormatterType::json:
{
return new JsonFormatter;
}
case FormatterType::invalid:
{
return nullptr;
}
}
return nullptr;
}
1条答案
按热度按时间vpfxa7rd1#
make_formatter
函数的定义假定命名空间解析将理解您正在定义core::log
中声明的命名空间解析。然而,事实并非如此。虽然
using namespace
会将标识符导入到当前命名空间中,但它不会以相反的方式工作。当您定义make_formatter
时,它不会仅仅因为该标识符存在而被推回到core::log
命名空间中。实际上,它将通过在全局名称空间中定义一个新函数来重载它:
问题的论证在这里:https://godbolt.org/z/4WTW4e1cf
所以链接器没有说谎。没有
core::log::make_formatter
的实现。您的选项包括:
1.明确限定它:
1.在正确的命名空间中定义它: