【问题标题】:Undefined Reference to vTable for constructor and destructor [duplicate]未定义对构造函数和析构函数的 vTable 的引用 [重复]
【发布时间】:2020-07-07 11:55:25
【问题描述】:

我有一个名为 AbstractHeap 的虚拟基类。 AbstractHeap 有一个虚函数“comp”。它还有一个(非虚拟的)构造函数和析构函数,所有已实现的派生类都应该使用它们。

AbstractHeap 由 MinHeap 继承。它实现了“comp”。它还有一个构造函数,它只调用基本构造函数。

最后,Main.cpp 只是创建了一个 MinHeap 的实例。

当我编译程序时,它给了我这个错误:

$ rm *.o && make
g++ -std=c++11 -c -g AbstractHeap.cpp
g++ -std=c++11 -c -g Main.cpp
g++ -std=c++11 -g -Wall Main.o AbstractHeap.o -o Main
Main.o: In function `MinHeap::MinHeap(int, int)':
/mnt/c/dev/Data_Structures/Lab7/MinHeap.h:8: undefined reference to `vtable for MinHeap'
/mnt/c/dev/Data_Structures/Lab7/MinHeap.h:8: undefined reference to `vtable for MinHeap'
collect2: error: ld returned 1 exit status
Makefile:2: recipe for target 'Main' failed
make: *** [Main] Error 1
owen@MatrixSword:/mnt/c/dev/Data_Structures/Lab7$ rm *.o && make
g++ -std=c++11 -c -g AbstractHeap.cpp
g++ -std=c++11 -c -g Main.cpp
g++ -std=c++11 -g -Wall Main.o AbstractHeap.o -o Main
Main.o: In function `MinHeap::MinHeap(int, int)':
MinHeap.h:8: undefined reference to `vtable for MinHeap'
MinHeap.h:8: undefined reference to `vtable for MinHeap'
Main.o: In function `MinHeap::~MinHeap()':
MinHeap.h:5: undefined reference to `vtable for MinHeap'
MinHeap.h:5: undefined reference to `vtable for MinHeap'
collect2: error: ld returned 1 exit status
Makefile:2: recipe for target 'Main' failed
make: *** [Main] Error 1

我查看了this 高度赞成的问题,但似乎问题和解决方案涉及我没有使用的 QT。

这是代码。

抽象堆.h

#ifndef ABSTRACT_HEAP_H
#define ABSTRACT_HEAP_H
#include <iostream>
#include <string>
using namespace std;

struct Item
{
    int key = -1;
    string data = "";
};

class AbstractHeap
{
    private:
        int k; //A k-heap.
        int size;
        Item* A; //The array.

    public:
        AbstractHeap(int k, int size);
        ~AbstractHeap();

        //Comparison operator. Can be interpretted as c comp b. So, if you want a <, comp is a<b. If the result is true, a has a higher priority than b.
        virtual bool comp(int a, int b) = 0;
};

#endif

抽象堆.cpp

#include "AbstractHeap.h"
#include <iostream>
#include <algorithm>
using namespace std;

AbstractHeap::AbstractHeap(int _k, int _size)
{
    size = _size;
    k = _k;
    A = new Item[size];
}

AbstractHeap::~AbstractHeap()
{
    delete [] A;
}

MinHeap.h

#ifndef MIN_HEAP_H
#define MIN_HEAP
#include "AbstractHeap.h"

class MinHeap : virtual public AbstractHeap
{
    public:
        MinHeap(int k, int size) : AbstractHeap{k, size} {};
        bool comp(int a, int b);
};

#endif

MinHeap.cpp

#include "MinHeap.h"

bool MinHeap::comp(int a, int b)
{
    return a < b;
}

最后,这是我的 Makefile,万一这是 Makefile 编写不佳的结果。

Main: AbstractHeap.o Main.o 
    g++ -std=c++11 -g -Wall Main.o AbstractHeap.o -o Main

Main.o: Main.cpp
    g++ -std=c++11 -c -g Main.cpp

AbstractHeap.o: AbstractHeap.cpp AbstractHeap.h MinHeap.cpp MinHeap.h
    g++ -std=c++11 -c -g AbstractHeap.cpp

编辑:问题已解决!问题其实是三个问题。

  1. 我删除了 MinHeap 声明中的“virtual”。 ("class MinHeap : public AbstractHeap")

  2. 我在 AbstractHeap 的析构函数前面添加了“虚拟”。 (“虚拟~AbstractHeap”)

  3. 我添加了一条编译规则来创建 MinHeap.o,如下所示:

Main: AbstractHeap.o Main.o MinHeap.o
    g++ -std=c++11 -g -Wall Main.o AbstractHeap.o MinHeap.o -o Main

Main.o: Main.cpp
    g++ -std=c++11 -c -g Main.cpp

AbstractHeap.o: AbstractHeap.cpp AbstractHeap.h MinHeap.cpp MinHeap.h
    g++ -std=c++11 -c -g MinHeap.cpp
    g++ -std=c++11 -c -g AbstractHeap.cpp

谢谢大家!

【问题讨论】:

  • 另外,我对提交 StackOverflow 问题还比较陌生,所以请善待 :)
  • 不会发生。我们是这里最纯粹的邪恶。注定!你死定了!呜呜呜哈哈哈哈哈哈哈哈哈!
  • 看看如果你将 ` ~AbstractHeap();` 更改为 virtual ~AbstractHeap(); 会发生什么。 You'll want to do it anyway.
  • 很好的问题 - 您从一开始就提供了所需的所有信息。
  • 查看你的makefile。将编译MinHeap.cpp 的命令在哪里? (它应该看起来像g++ -std=c++11 -c -g MinHeap.cpp。)现在交叉引用您以某种方式认为与QT有关的问题的答案:Undefined reference to vtable嗯:快速测试:在MinHeap.cpp 中放置一个明显的语法错误,然后重新构建您的项目。编译器抱怨了吗?

标签: c++ c++11 gcc


【解决方案1】:

两件事:

1) 这段代码不太可能是你想要的:

 class MinHeap : virtual public AbstractHeap

虚拟派生仅在您进行多重继承时使用(您不在这里,从您所展示的内容来看),即使那样最好避免。

你只需要:

class MinHeap : public AbstractHeap

我怀疑这会导致错误。

2) 如果你有一个基类,它的析构函数应该声明为virtual,所以:

virtual ~AbstractHeap();

如果不是,那么当你delete一个派生类对象时,派生类的析构函数可能会被跳过。因此,您需要在基类中使用 virtual 析构函数,即使它什么都不做且主体为空,因为好处在于派生类。

【讨论】:

  • 在析构函数体为空的情况下,查看virtual ~AbstractHeap() = default;是否对你可用
  • 这就是问题所在,谢谢!
猜你喜欢
  • 2016-09-26
  • 1970-01-01
  • 1970-01-01
  • 2014-06-08
  • 1970-01-01
  • 1970-01-01
  • 2015-05-25
  • 1970-01-01
相关资源
最近更新 更多