我有一个虚拟基类,称为 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
Run Code Online (Sandbox Code Playgroud)
我看过这个高度赞成的问题,但问题和解决方案似乎涉及 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
Run Code Online (Sandbox Code Playgroud)
抽象堆.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;
}
Run Code Online (Sandbox Code Playgroud)
最小堆.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
Run Code Online (Sandbox Code Playgroud)
最小堆.cpp
#include "MinHeap.h"
bool MinHeap::comp(int a, int b)
{
return a < b;
}
Run Code Online (Sandbox Code Playgroud)
最后,这是我的 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
Run Code Online (Sandbox Code Playgroud)
编辑:问题已解决!问题实际上是三个问题。
我在 MinHeap 的声明中删除了“virtual”。(“最小堆类:公共抽象堆”)
我在AbstractHeap中的析构函数前面添加了“virtual”。(“虚拟〜AbstractHeap”)
我添加了一条编译规则来创建 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
Run Code Online (Sandbox Code Playgroud)
感谢大家!
两件事情:
1)这段代码不太可能是你想要的:
class MinHeap : virtual public AbstractHeap
Run Code Online (Sandbox Code Playgroud)
虚拟派生仅在您进行多重继承时才有用(从您所展示的内容来看,您不在这里),即使如此,最好还是避免它。
您只需要:
class MinHeap : public AbstractHeap
Run Code Online (Sandbox Code Playgroud)
我怀疑这是导致错误的原因。
2)如果你有一个基类,它的析构函数应该声明为virtual,所以:
virtual ~AbstractHeap();
Run Code Online (Sandbox Code Playgroud)
如果没有,那么当你delete创建派生类对象时,派生类的析构函数可能会被跳过。因此,virtual即使它不执行任何操作并且具有空主体,您也需要在基类中使用析构函数,因为好处在于派生类。