C++ 链接错误:未定义对 `vtable for XXX` 的引用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7720205/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Linking error: undefined reference to `vtable for XXX`
提问by Amir
There is some linking error here. I looked for that online, yet still I couldn't find the problem. How can I fix it?
这里有一些链接错误。我在网上找了下,还是没找到问题所在。我该如何解决?
g++ test.cpp -o test
/tmp/ccDfCj4N.o: In function `Interval::Interval()':
test.cpp:(.text._ZN8IntervalC2Ev[Interval::Interval()]+0x9): undefined reference to `vtable for Interval'
/tmp/ccDfCj4N.o: In function `IntInterval::~IntInterval()':
test.cpp:(.text._ZN11IntIntervalD0Ev[IntInterval::~IntInterval()]+0x1d): undefined reference to `Interval::~Interval()'
/tmp/ccDfCj4N.o: In function `IntInterval::~IntInterval()':
test.cpp:(.text._ZN11IntIntervalD1Ev[IntInterval::~IntInterval()]+0x1d): undefined reference to `Interval::~Interval()'
/tmp/ccDfCj4N.o:(.rodata._ZTI11IntInterval[typeinfo for IntInterval]+0x10): undefined reference to `typeinfo for Interval'
collect2: ld returned 1 exit status
Here is the code! All classes are in a same file for a pilot program.
这是代码!试点项目的所有类都在同一个文件中。
#include <iostream>
#include <vector>
#include <utility>
using namespace std;
#define MAX_IP_RANGE 4294967295
class Interval {
public:
virtual Interval * interval_copy() = 0;
virtual unsigned long get_begin() = 0;
virtual unsigned long get_end() = 0;
virtual unsigned long get_length() = 0;
virtual Interval* get_intersect(Interval *interval) = 0; // Examine whether two intervals have intersection
virtual Interval* copy() = 0;
virtual ~Interval();
virtual bool is_equal(Interval *interval) {
unsigned long b1 = this->get_begin();
unsigned long e1 = this->get_end();
unsigned long b2 = interval->get_begin();
unsigned long e2 = interval->get_end();
if (b1 == b2 && e1 == e2)
return true;
return false;
}
virtual bool is_within(Interval *interval) {
unsigned long b1 = this->get_begin();
unsigned long e1 = this->get_end();
unsigned long b2 = interval->get_begin();
unsigned long e2 = interval->get_end();
if (b1 >= b2 && e1 <= e2)
return true;
return false;
}
virtual bool contains(Interval *interval) { // Examine whether this interval contains another interval
unsigned long b1 = this->get_begin();
unsigned long e1 = this->get_end();
unsigned long b2 = interval->get_begin();
unsigned long e2 = interval->get_end();
if (b1 <= b2 && e1 >= e2)
return true;
return false;
}
virtual bool is_empty() {
return (get_end()<get_begin())?true:false;
}
virtual bool is_intersect(Interval *interval) {
unsigned long b1 = this->get_begin();
unsigned long e1 = this->get_end();
unsigned long b2 = interval->get_begin();
unsigned long e2 = interval->get_end();
if (b1>e2)
return false;
if (b2>e1)
return false;
return true;
}
virtual void print()
{
cout << '('<<get_begin() << ',' << get_end() << ")\n";
}
};
class IntInterval : public Interval {
private:
unsigned long begin;
unsigned long end;
IntInterval();
public:
virtual Interval * interval_copy() {
return new IntInterval(begin, end);
}
IntInterval(unsigned long a, unsigned long b): begin (a), end (b)
{}
void set_value(unsigned long a, unsigned long b) {
begin = a;
end = b;
}
void set_begin(unsigned long a) {
begin = a;
}
void set_end(unsigned long b) {
end = b;
}
virtual Interval* copy()
{
Interval *new_interval = new IntInterval(begin, end);
return new_interval;
}
virtual unsigned long get_begin() {
return begin;
}
virtual unsigned long get_length() {
return end-begin+1;
}
virtual unsigned long get_end() {
return end;
}
virtual Interval* get_intersect(Interval *interval); // Get the intersect part of two intervals
virtual ~IntInterval() {};
};
Interval* IntInterval::get_intersect(Interval *interval) {
unsigned long begin2 = interval->get_begin();
unsigned long end2 = interval->get_end();
if (end < begin2 || begin > end2) {
return new IntInterval(1, 0);
}
return new IntInterval((begin>begin2)?begin:begin2, (end<end2)?end:end2);
}
IntInterval * parse_ip(const char * _str) {
unsigned long _begin=0;
unsigned long _end=0;
string input(_str);
if (input.find('-') != string::npos){
string begin = input.substr(0, input.find('-'));
string end = input.substr(input.find('-')+1);
unsigned int ip1 = 0, ip2 = 0;
unsigned int ip3 = 0, ip4 = 0;
sscanf(begin.c_str(), "%u.%u.%u.%u", &ip1, &ip2, &ip3, &ip4);
_begin = (ip1 << 24) + (ip2 << 16) + (ip3 << 8) + ip4;
ip1 = 0; ip2 = 0; ip3 = 0; ip4 = 0;
sscanf(end.c_str(), "%u.%u.%u.%u", &ip1, &ip2, &ip3, &ip4);
_end = (ip1 << 24) + (ip2 << 16) + (ip3 << 8) + ip4;
if ((_begin > _end) || (_end > MAX_IP_RANGE)){
cout<<"ERROR: The IP INTERVAL IS WRONG The range is "<<begin<<"-"<<end<<endl;
exit(0);
}
}
return new IntInterval(_begin, _end);
}
bool compFunc (Interval * i, Interval * j) {
return (i->get_begin() < j->get_begin());
}
int main () {
vector <vector<pair<string, string> > > nets;
vector<pair<string, string> > x;
vector<pair<string, string> > y;
x.push_back(make_pair("1.1.1.1", "3.0.0.0"));
x.push_back(make_pair("10.2.5.3", "30.2.5.0"));
x.push_back(make_pair("100.2.25.2", "130.2.25.2"));
y.push_back(make_pair("41.0.2.2", "43.2.2.5"));
y.push_back(make_pair("131.2.2.2", "135.5.5.2"));
nets.push_back(x);
nets.push_back(y);
vector <IntInterval *> _nets;
for (int i=0; i<(int)nets.size(); i++)
for(int j=0; j<(int)nets[i].size(); j++) {
string s = nets[i][j].first + '-' + nets[i][j].second;
_nets.push_back(parse_ip(s.c_str()));
}
sort(_nets.begin(), _nets.end(), compFunc);
if (_nets.size()>1)
for (vector<IntInterval *>::iterator it = _nets.begin()+1; it < _nets.end(); ) {
if ((*it)->get_begin()-1 == (*(it-1))->get_end()) {
(*(it-1))->set_end((*it)->get_end());
_nets.erase(it);
}
else if ((*it)->get_begin()-1 < (*(it-1))->get_end()) {
it++;
cout<<"ERROR: Network address overlapping!"<<endl;
}
else
it++;
}
for (int i=0; i<(int)_nets.size(); i++)
cout << _nets[i]->get_begin() << " " << _nets[i]->get_end() << endl;
return 0;
}
回答by bdonlan
You never provided an implementation for virtual ~Interval();
and several other functions. You must provide an implementation for all non-pure virtual functions you declare. In particular, G++ emits the vtable along with the implementation of the first-declared non-inline function in a class. Omitting its implementation means you won't have a vtable, and thus won't be able to construct the class (hence these errors).
您从未提供过virtual ~Interval();
和其他几个函数的实现。您必须为您声明的所有非纯虚函数提供一个实现。特别是,G++ 发出 vtable 以及类中第一个声明的非内联函数的实现。省略其实现意味着您将没有 vtable,因此将无法构造该类(因此会出现这些错误)。
In short, define every function you declare, except for pure virtuals. There are some caseswhere it's justified to leave out the definition for a declared function, but they are very rare.
简而言之,定义您声明的每个函数,纯虚函数除外。在某些情况下,省略已声明函数的定义是合理的,但这种情况非常罕见。
回答by scorpiodawg
I had the same problem. I was merging my code with upstream changes and picked my change over another engineer's seemingly identical change in the header file. It just turned out that they had changed the constness of the method and I hadn't noticed, and you will get this error for the reason @bdonian says.
我有同样的问题。我正在将我的代码与上游更改合并,并选择我的更改而不是另一位工程师在头文件中看似相同的更改。事实证明,他们改变了方法的常量性,而我没有注意到,由于@bdonian 所说的原因,您将收到此错误。
virtual void foo(Many params, As part, Of veryLong, Method signature);
and theirs:
和他们的:
virtual void foo(Many params, As part, Of veryLong, Method signature) const;
When merging I picked the first version, but the implementation had the second one, resulting in the compiler assuming there is an overload of foo() that is undefined, and hence the error.
合并时我选择了第一个版本,但实现有第二个版本,导致编译器假设存在未定义的 foo() 重载,因此出现错误。
回答by Dani
In virtual classes never put undefined functions first. Move
在虚拟类中,永远不要把未定义的函数放在第一位。移动
IntInterval();
to after the first defined function:
在第一个定义的函数之后:
private:
unsigned long begin;
unsigned long end;
public:
virtual Interval * interval_copy(){return new IntInterval(begin,end);}
IntInterval(unsigned long a,unsigned long b): begin (a),
end (b)
{}
private:
IntInterval();
public:
It's because C++ glues the vtable to the first function. If you don't define it, the vtable will be undefined as well.
这是因为 C++ 将 vtable 粘在第一个函数上。如果你不定义它,vtable 也将是未定义的。
As mentioned by other answers, you need to also define the destructor:
正如其他答案所述,您还需要定义析构函数:
public:
virtual ~IntInterval()
{
// Destruction code
}