仅在 MacOS 上析构函数的未定义符号

Undefined symbol to destructor only on MacOS

本文关键字:未定义 符号 析构函数 MacOS 仅在      更新时间:2023-10-16

在我正在处理的库中,我在头文件中有类似这个模板类的东西:

template <int something>
class Base {
public:
virtual ~Base();  // Implemented in c++ file
}
class Derived : public Base<100> {
public:
~Derived() override = default();
}

析构函数的实现方式如下:

template <int something>
Base<something>::~Base() {
destroyBase();
}

此代码编译为静态库。

然后,我在示例中有以下代码:

{
Derived x;
x.doSomething();
} // X gets destroyed

我编译可执行文件并链接静态库。这在 Ubuntu 上工作正常,但是当我在 Mac 上尝试时,链接失败

Undefined symbols for architecture x86_64:
"Base<100>::~Base()", referenced from:
_main in my_sample.cpp.o

在这两种情况下,我都使用 clang 并使用完全相同的 cmake 设置进行编译。将定义 cpp 文件中定义的所有其他符号。这是唯一未定义的符号。发生了什么事情?

正如Sebastian Hoffmann所说,模板必须在头文件中实现,而不是在cpp文件中实现,否则它将不可见。这就是为什么我得到未定义的符号。

当我在头文件中实现所有内容时,Mac 上的构建现在可以工作。 尽管如此,这并不能解释为什么这只发生在 Mac 上,但在 ubuntu 上完美运行。另外,为什么只有析构函数?我在 cpp 文件中实现了Base的其他成员函数,它们链接得很好!

更新:我认为只有析构函数无法链接的原因是它是客户端应用程序直接引用的唯一一个。构造函数仅通过派生类构造函数引用,其他成员函数和运算符 = 以及东西从未实际调用过。从 c++ 的角度来看,链接器错误是有道理的,但 Mac 和 ubuntu 之间的差异令人费解。

注意:我正在使用travis ci进行构建,这实际上是我在 https://github.com/RotartsiORG/StoneMason 的个人爱好项目(不是很好(