【问题标题】:C++ Undefined Reference to vtable and inheritanceC++ 未定义对 vtable 和继承的引用
【发布时间】:2012-03-13 11:26:06
【问题描述】:

文件 A.h

#ifndef A_H_
#define A_H_

class A {
public:
    virtual ~A();
    virtual void doWork();
};

#endif

文件 Child.h

#ifndef CHILD_H_
#define CHILD_H_

#include "A.h"

class Child: public A {
private:
    int x,y;
public:
    Child();
    ~Child();
    void doWork();
};
#endif

和 Child.cpp

#include "Child.h"

Child::Child(){
    x = 5;
}

Child::~Child(){...}

void Child::doWork(){...};

编译器说A 有一个未定义的vtable 引用。 我尝试了很多不同的方法,但都没有奏效。

我的目标是让A 类成为一个接口,并将实现代码与标头分开。

【问题讨论】:

  • 你必须定义你声明的每一个非纯虚函数。您不需要定义您声明但不使用的非虚拟函数。

标签: c++ inheritance vtable


【解决方案1】:

为什么会出现错误以及如何解决?

您需要为class A 中的所有虚函数提供definitions。只有纯虚函数才允许没有定义。

即:class A 两种方法:

virtual ~A();
virtual void doWork();

应该被定义(应该有一个主体)

例如:

A.cpp

void A::doWork()
{
}
A::~A()
{
}

警告:
如果您希望您的 class A 充当接口(在 C++ 中也称为 Abstract class),那么您应该将该方法设为纯虚拟。

virtual void doWork() = 0;

好读:

What does it mean that the "virtual table" is an unresolved external?
When building C++, the linker says my constructors, destructors or virtual tables are undefined.

【讨论】:

  • @user1227351:更新了答案以更好地解释。阅读链接以获得进一步的解释。
  • 拥有虚拟的~A();虚空doWork() = 0;仍然给出 vtable 错误 =/。但是没有析构函数它工作正常。但是,如果没有它,如果我执行以下操作: A *a = new Child();删除一个;显然它不会调用 Child::~Child()。有解决办法吗?
  • 解决方法是将A::~A(){}放在Child.cpp中
  • 使用 C++11,您可以使用“default”关键字让编译器完成这项工作。例如:虚拟 doSomething() = 默认;
【解决方案2】:

我的目标是让 A 成为一个接口,并将实现代码与标头分开。

在这种情况下,将成员函数设为 A 类中的纯虚函数。

class A {
  // ...
  virtual void doWork() = 0;
};

【讨论】:

  • 如果我也删除了析构函数,这将删除错误。在这种情况下,如果我这样做: A a = new Child();删除一个;它会调用什么析构函数?
  • 破坏总是与构造相反。在这种情况下,类A 析构函数必须是虚拟的,它强制首先调用Child 析构函数,然后调用A 析构函数。如果A 类析构函数不是虚拟的,则行为未定义。
  • 它将调用子类的析构函数,因为您已将父类析构函数设为虚拟。之后,父类的析构函数。
  • 在 A 中同时拥有析构函数和纯虚拟 doWork() 会导致 vtable 错误。我如何定义一个虚拟析构函数,以便: A *a = new Child();删除一个;导致调用 Child::~Child()?
  • 解决方法是将A::~A(){}放在Child.cpp中
【解决方案3】:

如果其他回复对您没有帮助,请确保删除所有“*.gch”文件。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-08
    • 2014-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-19
    相关资源
    最近更新 更多