6

我的代码中出现链接器错误。我已将其归结为以下基本要素。

此代码给出了链接器错误“vtable for Foo”,引用自:Foo::Foo()

class Foo {
public:
  Foo();
  virtual ~Foo() = default;
};
Foo::Foo() { }

但是这段代码没有给出任何错误:

class Foo {
public:
  Foo();
  virtual ~Foo() { }
};
Foo::Foo() { }

为什么?我认为= default应该基本上和那些空方括号做同样的事情。

更新:我正在使用“Apple LLVM 编译器 4.1”,它是 Xcode 4.5.2 的一部分。这可能是这个编译器中的一个错误吗?它可能适用于最新的 GCC(尽管 Apple 不再发布)。有关编译器的讨论,请参见下面的评论。

更新 2:如下所述,更改行以virtual inline ~Foo() = default;消除此错误。这不只是一个错误吗?在这种情况下,如果没有明确写出,编译器似乎无法识别内联函数inline

4

3 回答 3

3

这似乎是一个已经修复的clang中的错误。您问得恰到好处,因为很快就会有新版本发布:候选版本已经可用。请试一试,您的示例适用于 i386-linux 二进制版本,并且应该适用于所有这些版本。

于 2012-12-15T22:32:27.627 回答
2

在 Itanium ABI 中,为包含未在类中内联定义的第一个虚拟方法的定义的翻译单元发出 v 表(和其他 RTTI 信息),或者如果只有内联定义的虚拟方法,则针对每个翻译单元包括类。然后由链接器来合并冗余符号。

通过指定= default,Clang 可能没有意识到您已经在类中定义virtual内联方法,并且包含您的文件的每个 TU 都应该定义 v-table 和 RTTI 信息,而是等待定义出现某处。

我可以建议将定义放在课堂之外吗?=>Foo::~Foo() = default;

于 2012-12-15T15:54:53.297 回答
1

它适用于 g++ 4.7.2。但是我和你的clang 3.1有同样的问题。

我有 3 个文件。

富.h:

#ifndef FOO_H
#define FOO_H

class Foo {
public:
  Foo();
  virtual ~Foo() = default;
};

#endif // FOO_H

Foo.cpp:

#include "Foo.h"

Foo::Foo() { }

主.cpp:

#include <iostream>
#include "Foo.h"

using namespace std;

int main()
{
    Foo foo;
    return 0;
}

但如果是这样,它也适用于 clang:

Foo.cpp 为空。

主文件

#include <iostream>
#include "Foo.h"

using namespace std;

Foo::Foo() { }

int main()
{
    Foo foo;
    return 0;
}

所以我猜clang在生成目标文件时有错误。

于 2012-12-15T11:53:27.440 回答