链接错误:对“XXX 的 vtable”的未定义引用
这里有一些链接错误。我在网上查了一下,还是没找到问题所在。我该如何修复它?
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
这是代码! 所有课程都位于试点计划的同一个文件中。
#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;
}
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;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您从未提供 virtual ~Interval(); 和其他几个函数的实现。您必须为您声明的所有非纯虚函数提供实现。特别是,G++ 发出 vtable 以及类中第一个声明的非内联函数的实现。省略它的实现意味着您将没有 vtable,因此无法构造该类(因此会出现这些错误)。
简而言之,定义您声明的每个函数(纯虚函数除外)。在某些情况中,有理由离开给出已声明函数的定义,但这种情况非常罕见。
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).In short, define every function you declare, except for pure virtuals. There are some cases where it's justified to leave out the definition for a declared function, but they are very rare.
我也有同样的问题。我将我的代码与上游更改合并,并选择我的更改而不是另一个工程师在头文件中看似相同的更改。事实证明,他们改变了方法的常量性,而我没有注意到,并且由于 @bdonian 所说的原因,您会收到此错误。
和他们的:
合并时我选择了第一个版本,但实现有第二个版本,导致编译器假设存在未定义的 foo() 重载,因此出现错误。
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.
and theirs:
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.
在虚拟类中,永远不要将未定义的函数放在第一位。移至
第一个定义的函数之后:
这是因为 C++ 将 vtable 粘合到第一个函数。如果你不定义它,vtable也将是未定义的。
正如其他答案所提到的,您还需要定义析构函数:
In virtual classes never put undefined functions first. Move
to after the first defined function:
It's because C++ glues the vtable to the first function. If you don't define it, the vtable will be undefined as well.
As mentioned by other answers, you need to also define the destructor: