我实现了一个生成前 n 个斐波那契数的函数作为编码练习。为了增加在溢出任何标准整数类型之前可以生成的数字量,我从 github 下载了 BigInt 标头并将其放入
/usr/include
(ubuntu 22.04.4)。
当所有内容都保存在单个 .cpp 文件中时,不会给出错误,但在尝试将所有斐波那契相关内容移至其自己的翻译单元中时遇到问题。以下代码足以重现该错误:
测试.cpp:
#include "test_import.h"
int main() {}
test_import.h:
#ifndef TEST_IMPORT
#define TEST_IMPORT
#include <BigInt.hpp>
#endif
test_import.cpp:
#include "fibonacci.h"
这会为
<BigInt.hpp>
中的每个函数生成多定义链接器错误,例如如下所示:
/usr/bin/ld: CMakeFiles/test.dir/test_import.cpp.o: 在函数
is_valid_number(std::__cxx11::basic_stringbool std::__constant_string_p<char>(char const*)': /usr/include/BigInt.hpp:140: multiple definition of
const&)'; CMakeFiles/test.dir/test.cpp.o:/usr/include/BigInt.hpp:140:第一个 定义在这里
但我不明白为什么这会产生链接器错误。
编译器为:gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
这是我的 CMakeLists.txt 如果它提供了任何有用的信息:
set(PROJECT_NAME chap8)
cmake_minimum_required(VERSION 3.22)
project(${PROJECT_NAME} VERSION 1.0)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
include_directories("/usr/include/boost_1_85_0") #adds bosst library headers (most does not need to be built)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(TARGET_NAME test)
add_executable(${TARGET_NAME} "${TARGET_NAME}.cpp" "test_import.cpp")
target_compile_options(${TARGET_NAME} PRIVATE
-std=c++17
-fexceptions
-Wall
-g
-Wmissing-declarations
)
这是一个库问题。头文件中定义的函数应声明为
inline
。这会阻止链接器尝试跨翻译单元解析多个定义。该库的设计似乎并未考虑到多源项目。
要在本地修复此问题,请编辑已发布的
BigInt.hpp
标头,并在每个函数定义前面添加 inline
。
示例:
/*
is_valid_number
---------------
Checks whether the given string is a valid integer.
*/
inline bool is_valid_number(const std::string& num) {
for (char digit : num)
if (digit < '0' or digit > '9')
return false;
return true;
}
您可能也需要对成员函数定义执行此操作。
示例:
/*
Default constructor
-------------------
*/
inline BigInt::BigInt() {
value = "0";
sign = '+';
}
这应该在库本身中修复。您可以按照创建拉取请求的指南自行完成此操作。如果您没有信心这样做,请记录问题。
源已在以下位置分成多个标头,这些标头可能都需要此修复:
include/constructors/*.hpp
include/functions/*.hpp
include/operators/*.hpp