0

私はいくつかのコードを書きましたが、それをコンパイルすることができません:

#include <cstdio>
#include <vector>

名前空間stdを使用します。

クラスビジター;

クラスランド{
  公衆:
    virtual void accept(const Visitor * v);
};

クラスイングランド:公有地{
  公衆:
    void accept(const Visitor * v);
};

クラスロシア:公有地{
  公衆:
    void accept(const Visitor * v);
};

クラスビジター{
  公衆:
    void visit(const England * e)const;
    void visit(const Russia * r)const;
};

修学旅行 {
  プライベート:
    vector <Land> * l;
  公衆:
    明示的なTrip(vector <Land> * _l);
    void accept(Visitor * v);
};

/ ** /

void Visitor :: visit(const England * e)const {
  printf( "ねえ、イギリスだ!\ n");
}

void Visitor :: visit(const Russia * r)const {
  printf( "ねえ、それはロシアです!\ 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(){
  イングランドイングランド;
  ロシアロシア;
  vector <Land> trip_plan;
  trip_plan.push_back(england);
  trip_plan.push_back(ロシア);
  trip_plan.push_back(england);
  トリップ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):「vtableforLand」への未定義の参照
/tmp/ccNanCPR.o:関数 `Land :: Land(Land const&)':
vp.cc:(.text._ZN4LandC1ERKS_ [Land :: Land(Land const&)] + 0x13):「vtableforLand」への未定義の参照
/tmp/ccNanCPR.o:関数 `Land ::〜Land()':
vp.cc:(。text._ZN4LandD1Ev[Land::〜Land()] + 0xf):「vtableforLand」への未定義の参照
/tmp/ccNanCPR.o:(.rodata._ZTI6Russia[ロシアのtypeinfo]+0x10):「Landのtypeinfo」への未定義の参照
/tmp/ccNanCPR.o:(.rodata._ZTI7England [typeinfo for England] + 0x10): `typeinfoforLand'への未定義の参照
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

これはおそらくあなたが求めていることをはるかに超えていますが、設計の観点からは、土地固有のものは各土地のクラス内にある必要があると思います。

一方、ロシアとイングランドの accept() メンバーは同じであり、土地に移動する必要があります。

これをどのように構成するかを次に示します (accept()、arrive()、および 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 に答える
1

Land::accept メソッドを実装するか、純粋仮想として宣言します。

ただし、メインで問題が発生する可能性があることを発見しました。

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

型ベクトルが何であるかはわかりませんが、基本クラス値のベクトルに挿入される派生クラス オブジェクトを提供する際に問題が発生する可能性があります (型スライシング)。

于 2009-11-17T13:30:31.133 に答える
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*>ないように使用する必要があります。また、次回はイテレータの使用を検討するかもしれません。englandrussiaLandTrip::accept

于 2009-11-17T14:00:15.327 に答える
0

私はさらに2つのことを見ています:

1)サイズの前に「<」がないことに注意してください

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

2)(あなたの例を正しく理解していると仮定して)ベクトルはvector <Land>である必要があると思います(抽象的なLandのベクトルを作成し、それを具体的な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

わかりました、これが完全に機能するサンプルです(あなたがあなたのものから切り取られたかどうかはわかりません)。ここでコンパイルしていて、変更を加えたすべての場所に「!!!」でマークを付けました。コメント:

#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 に答える