我写了一些代码,但我无法编译它:
#include <cstdio> #include <vector> using namespace std; class Visitor; class Land { public: virtual void accept(const Visitor *v); }; class England : public Land { public: void accept(const Visitor *v); }; class Russia : public Land { public: void accept(const Visitor *v); }; class Visitor { public: void visit(const England *e) const; void visit(const Russia *r) const; }; class Trip { private: vector<Land> *l; public: explicit Trip(vector<Land> *_l); void accept(Visitor *v); }; /**/ void Visitor::visit(const England *e) const { printf("Hey, it's England!\n"); } void Visitor::visit(const Russia *r) const { printf("Hey, it's Russia!\n"); } void Russia::accept(const Visitor *v) { v->visit(this); } void England::accept(const Visitor *v) { v->visit(this); } Trip::Trip(vector<Land> *_l):l(_l) {} void Trip::accept(Visitor *v) { for (unsigned i = 0; i < l->size(); i++) { l->at(i).accept(v); } } int main() { England england; Russia russia; vector<Land> trip_plan; trip_plan.push_back(england); trip_plan.push_back(russia); trip_plan.push_back(england); Trip my_trip(&trip_plan); Visitor me; my_trip.accept(&me); return 0; }
这是我从g ++获得的:
c++ -ansi -Wall -Wextra -Wconversion -pedantic -Wno-unused-parameter -o vp vp.cc /tmp/ccNanCPR.o: In function `Land::Land()': vp.cc:(.text._ZN4LandC2Ev[Land::Land()]+0xf): undefined reference to `vtable for Land' /tmp/ccNanCPR.o: In function `Land::Land(Land const&)': vp.cc:(.text._ZN4LandC1ERKS_[Land::Land(Land const&)]+0x13): undefined reference to `vtable for Land' /tmp/ccNanCPR.o: In function `Land::~Land()': vp.cc:(.text._ZN4LandD1Ev[Land::~Land()]+0xf): undefined reference to `vtable for Land' /tmp/ccNanCPR.o:(.rodata._ZTI6Russia[typeinfo for Russia]+0x10): undefined reference to `typeinfo for Land' /tmp/ccNanCPR.o:(.rodata._ZTI7England[typeinfo for England]+0x10): undefined reference to `typeinfo for Land' collect2: ld returned 1 exit status
答案 0 :(得分:6)
我已经answered了。 vtable实例化的规则在编译器文档中有解释。
在这里,它正在等待 Land :: accept 的定义(正文),你声明它是非纯虚拟的,但从未定义过。 定义它,或使其成为纯虚拟。
答案 1 :(得分:2)
如果你没有实现一个虚函数(即它是否被后代覆盖),你需要通过'= NULL'将它标记为它(然后它被称为纯虚函数)。
class Land {
public:
virtual void accept(const Visitor *v)= 0; // pure virtual function
};
答案 2 :(得分:1)
实施Land :: accept方法或将其声明为纯虚拟。
但是,我发现主要可能存在问题:
trip_plan.push_back(england);
trip_plan.push_back(russia);
trip_plan.push_back(england);
我不知道什么类型的向量,但是您可能会遇到一个问题,即将派生类对象插入基类值的向量中(Type Slicing)。
答案 3 :(得分:1)
这可能远远超出你的要求,但从设计的角度来看,我认为特定于土地的东西应该在每个土地的类中,即它让我有点烦恼看到重载的visit()函数访客。
另一方面,俄罗斯和英格兰的接受()成员是相同的,应该被移到土地上。
以下是我将如何构建它(看看使用accept(),arri()和name()):
#include <cstdio>
#include <vector>
using namespace std;
class Visitor;
class Land {
public:
virtual void accept(const Visitor *v);
virtual void arrive(void) const = 0;
virtual const char *name(void) const = 0;
};
class England : public Land {
public:
void arrive(void) const;
const char *name(void) const;
};
class Russia : public Land {
public:
void arrive(void) const;
const char *name(void) const;
};
class Visitor {
public:
void visit(const Land *l) const;
};
class Trip {
private:
vector<Land *> *l;
public:
Trip(vector<Land *> *_l);
void accept(Visitor *v);
};
/**** Implementations *****/
// underlying Land
void Land::accept(const Visitor *v) {
v->visit(this);
}
// England
const char *England::name(void) const {
return "England";
}
void England::arrive(void) const {
printf("Welcome to our lovely country, your passport please\n");
}
// Russia
const char *Russia::name(void) const {
return "Russia";
}
void Russia::arrive(void) const {
printf("Passport!!\n");
}
// Visitor
void Visitor::visit(const Land *l) const {
l->arrive();
printf("Hey, it'm in %s!\n", l->name());
}
// Trip
Trip::Trip(vector<Land *> *_l)
: l(_l) // !!! <Land *>
{
}
void Trip::accept(Visitor *v) {
for (unsigned i = 0; i < l->size(); i++) {
l->at(i)->accept(v);
}
}
/**** main *****/
int main()
{
England england;
Russia russia;
vector<Land *> trip_plan;
trip_plan.push_back(&england);
trip_plan.push_back(&russia);
trip_plan.push_back(&england);
Trip my_trip(&trip_plan);
Visitor me;
my_trip.accept(&me);
return 0;
}
答案 4 :(得分:0)
我还看到了两件事:
1)注意缺少“&lt;”尺寸之前
void Trip::accept(Visitor *v) {
for (unsigned i = 0; i < size(); i++) {
l->at(i).accept(v);
}
}
2)我认为(假设我理解你的例子)矢量应该是vector&lt;土地&gt; (你正在构建一个抽象的Lands矢量,然后用指向具体Land对象的指针填充)
vector<Land> Trip;
或
typedef vector<Land> trip_t; // type for a trip is a vector of Lands
...
trip_t Trip;
(在我撰写此评论时,您似乎仍在编辑示例,因此我将不得不采用更一般的答案)。
答案 5 :(得分:0)
我认为您使用vector
的位置应该使用std::vector<Land*>
:
class Trip {
private:
std::vector<Land*> *l; // vector of pointers to Land
public:
explicit Trip(std::vector<Land*> *_l);
void accept(Visitor *v);
};
和
void Trip::accept(Visitor *v) {
for (unsigned i = 0; i< l->size(); i++) {
l->at(i)->accept(v); // . changed to ->
}
}
和
int main() {
England england;
Russia russia;
std::vector<Land*> trip_plan;
trip_plan.push_back(&england); // push_back pointers
trip_plan.push_back(&russia);
trip_plan.push_back(&england);
Trip my_trip(&trip_plan);
Visitor me;
my_trip.accept(&me);
return 0;
}
您需要使用<Land*>
,这样才不会将england
和russia
切片为Land
的实例。
另外,您可能会考虑下次在Trip::accept
中使用迭代器。
答案 6 :(得分:0)
好的,这是一个完整的工作样本(不确定你的剪辑是否已被剪裁)。它在这里编译,我用“!!!”标记了我所做的所有改动的地方注释:
#include <cstdio>
#include <vector>
using namespace std;
class Visitor;
class Land {
public:
virtual void accept(const Visitor *v)= 0; // !!! = 0
};
class England : public Land {
public:
void accept(const Visitor *v);
};
class Russia : public Land {
public:
void accept(const Visitor *v);
};
class Visitor {
public:
void visit(const England *e) const;
void visit(const Russia *r) const;
};
class Trip {
private:
vector<Land *> *l; // !!! <Land *>
public:
Trip(vector<Land *> *_l); // !!! <Land *>
void accept(Visitor *v);
};
/* Implementations */
void Visitor::visit(const England *e) const {
printf("Hey, it's England!\n");
}
void Visitor::visit(const Russia *r) const {
printf("Hey, it's Russia!\n");
}
void Russia::accept(const Visitor *v) {
v->visit(this);
}
void England::accept(const Visitor *v) {
v->visit(this);
}
Trip::Trip(vector<Land *> *_l) : l(_l) // !!! <Land *>
{
}
void Trip::accept(Visitor *v) {
for (unsigned i = 0; i < l->size(); i++) { // !!! i < l->size()
l->at(i)->accept(v); // !!! at(i)->accept()
}
}
int main()
{
England england;
Russia russia;
vector<Land *> trip_plan; // !!! <Land *>
trip_plan.push_back(&england); // !!! &england
trip_plan.push_back(&russia); // !!! &russia
trip_plan.push_back(&england); // !!! &england
Trip my_trip(&trip_plan);
Visitor me;
my_trip.accept(&me);
return 0;
}