0

我写了一些代码,但我无法编译它:

#include <cstdio>
#include <向量>

使用命名空间标准;

类访客;

类土地{
  上市:
    virtual void accept(const 访问者 *v);
};

英格兰类:公共土地{
  上市:
    无效接受(常量访问者 *v);
};

俄罗斯类:公共土地{
  上市:
    无效接受(常量访问者 *v);
};

类访客{
  上市:
    无效访问(常量英格兰 *e)常量;
    无效访问(常量俄罗斯 *r)常量;
};

班级旅行 {
  私人的:
    矢量<土地> *l;
  上市:
    显式旅行(矢量<土地> *_l);
    无效接受(访客*v);
};

/**/

void 访客::visit(const England *e) const {
  printf("嘿,这里是英格兰!\n");
}

void 访客::visit(const 俄罗斯 *r) const {
  printf("嘿,这是俄罗斯!\n");
}

无效俄罗斯::accept(const 访问者 *v) {
  v->访问(这个);
}

void England::accept(const Visitor *v) {
  v->访问(这个);
}

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() {
  英格兰英格兰;
  俄罗斯俄罗斯;
  矢量<土地> 旅行计划;
  trip_plan.push_back(英格兰);
  trip_plan.push_back(俄罗斯);
  trip_plan.push_back(英格兰);
  行程 my_trip(&trip_plan);
  拜访我;
  my_trip.accept(&me);
  返回0;
}

这是我从 g++ 得到的:

c++ -ansi -Wall -Wextra -Wconversion -pedantic -Wno-unused-parameter -o vp vp.cc
/tmp/ccNanCPR.o:在函数“Land::Land()”中:
vp.cc:(.text._ZN4LandC2Ev[Land::Land()]+0xf): undefined reference to `vtable for Land'
/tmp/ccNanCPR.o:在函数“Land::Land(Land const&)”中:
vp.cc:(.text._ZN4LandC1ERKS_[Land::Land(Land const&)]+0x13): 未定义对“vtable for Land”的引用
/tmp/ccNanCPR.o:在函数“Land::~Land()”中:
vp.cc:(.text._ZN4LandD1Ev[Land::~Land()]+0xf): 未定义对“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 返回 1 个退出状态

这个问题是基于声明的循环依赖

4

7 回答 7

6

我已经在那里回答了。vtable 实例化的规则在您的编译器文档中进行了说明。

在这里,它正在等待查看Land::accept的定义(主体) ,您声明它是一个非纯虚拟,但从未定义过。要么定义它,要么让它成为纯虚拟的。

于 2009-11-17T13:27:01.063 回答
2

如果你没有实现一个虚函数(即如果它被后代覆盖),你需要通过'=NULL'来标记它(然后它被称为纯虚函数)。

class Land {
  public:
    virtual void accept(const Visitor *v)= 0;   // pure virtual function
};
于 2009-11-17T13:27:03.277 回答
1

实现 Land::accept 方法或将其声明为纯虚拟。

但是,我在 main 中发现了一个可能的问题:

trip_plan.push_back(england);
trip_plan.push_back(russia);
trip_plan.push_back(england);

我不知道什么是类型向量,但您可能在提供要插入基类值向量中的派生类对象(类型切片)时遇到问题。

于 2009-11-17T13:30:31.133 回答
1

这可能远远超出了您的要求,但从设计的角度来看,我认为土地特定的东西应该在每个土地的类中,即看到 Visitor 中的重载的 visit() 函数让我有点恼火。

另一方面,俄罗斯和英国的 accept() 成员是相同的,应该向上移动到 Land 中。

以下是我将如何构建它(看看accept()、arrange()和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;
}
于 2009-11-17T14:23:52.773 回答
0

我看到了另外两件事:

1)注意大小前缺少的“<”

void Trip::accept(Visitor *v) {
  for (unsigned i = 0; i < size(); i++) {
    l->at(i).accept(v);
  }
}

2)我认为(假设我正确理解您的示例)向量应该是 vector< Land > (您正在构建一个抽象 Lands 的向量,然后填充指向具体 Land 对象的指针)

 vector<Land> Trip;

或者

 typedef vector<Land> trip_t;  // type for a trip is a vector of Lands
 ... 

 trip_t Trip;

(在我撰写此评论时,您目前似乎仍在编辑示例,因此我将不得不使用更一般的答案)。

于 2009-11-17T13:41:49.053 回答
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*>,这样您就不会englandrussia分到Land. 此外,您下次可能会考虑使用迭代器Trip::accept

于 2009-11-17T14:00:15.327 回答
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;
}
于 2009-11-17T14:04:46.243 回答