【问题标题】:Strange error message when a class method is missing [duplicate]缺少类方法时出现奇怪的错误消息[重复]
【发布时间】:2011-09-25 12:17:40
【问题描述】:

可能重复:
GCC C++ Linker errors: Undefined reference to 'vtable for XXX', Undefined reference to 'ClassName::ClassName()'

由于一个奇怪的 ld 错误,我一直在用头撞墙很长时间。 所以我把它复制在一个小测试用例中来理解这个问题。

我声明了一个类,并在头文件中派生了另一个类:

class BaseClass {
public:
  BaseClass(){};
  virtual void func(){};
};

class DerivedClass: public BaseClass {
public:
  DerivedClass();
  void func();
};

然后我定义了构造函数但忘记定义func(这里是自愿的,但实际上我用愚蠢的复制/粘贴...):

DerivedClass::DerivedClass(){
  cout << "Derived constructor" << endl;
}

//void DerivedClass::func(){
//  cout << "Derived func" << endl;
//}

然后我得到:

对 `vtable for DerivedClass' 的未定义引用

编辑:消息指向构造函数的声明!

如果我取消注释func 的定义,那么我没有错误。所以我的问题: 为什么链接器没有告诉我缺少func 的定义?

当您有经验时,解决方案可能很明显,但对于像我这样的初学者来说,这不是!

感谢您的帮助。

【问题讨论】:

标签: c++ oop ld


【解决方案1】:

vtable 是为包含虚函数的类和从它派生的类创建的。这意味着在您的程序中,vtable 将为BaseClassDerivedClass 创建。这些vtables 中的每一个都将包含虚函数void func()的地址。现在注意DerivedClass不包含void func()的定义,因此它的vtable包含BaseClassvoid func()函数的地址。这就是为什么编译器给出错误undefined reference to vtable for DerivedClass

【讨论】:

  • 如果我很好理解上面 Raymond Chen 给出的GCC FAQ,我想你几乎是对的。我不明白的是链接器在类构造函数上失败了(但我忘了在这里提到这个......)。并且在构造函数和析构函数之间定义第一个方法时链接会失败(可能是其他方法,但我不确定)。
【解决方案2】:

您的编译器似乎没有为DerivedClass 生成vtablevtable 基本上是一个包含每个虚函数的函数指针的表。通过为每个对象存储指向类的vtable(通常称为vptr)的指针,可以在运行时确定要调用的正确虚函数。虽然是具体编译器的实现细节,但这是实现虚函数的常用方式,虚函数是在运行时绑定的,因此不能像普通函数一样调用。

我的第一个猜测是编译器没有为DerivedClass 生成vtable,因为它没有定义任何虚函数,所以它使用BaseClassvtable。虽然这有点奇怪,但这是我能想到的唯一想法。但我对编译器架构不是那么精通,也许有人有更好的解决方案。

【讨论】:

  • 基本上答案是它不是由 ld 处理的!无论如何,谢谢你的解释。
猜你喜欢
  • 2021-07-01
  • 1970-01-01
  • 2021-05-30
  • 2020-06-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-18
  • 2018-05-03
相关资源
最近更新 更多