2

ツアーとガイド付きツアー。GuideTour は Tour を拡張します。これらのアイテムのリストを作成し、ベクターに追加します。

 list = new vector<Tour>(); 
 list->push_back(Tour("FP001", "Fun Park 3 Day Pass", 110.00));
 list->push_back(Tour("BG002", "Botanical Gardens Entry Pass", 30.00));
 list->push_back(GuidedTour("SK003", "Learn to Ski Adventure Tour", 240.00, "28/07/2008", "Zail S", 25));
 list->push_back(Tour("OZ004", "Open Range Zoo Entry Pass", 45.00));
 list->push_back(GuidedTour("AB005", "Abseiling for Beginners Tour", 120.00, "15/07/2008", "Rex P", 35));
 list->push_back(GuidedTour("RA006", "White Water Rafting Tour", 200.00, "22/06/2008", "Clint R", 16));

次に、この配列を調べて、これらのオブジェクトのタイプを確認したいと思います

void TourManager::callDisplayOnEach() {
    for (vector<Tour>::iterator it = list->begin(); it != list->end(); ++it) {
        if (typeid(*it) == typeid(GuidedTour)) {
            cout << "Guided Tour" << "\n";
        }
        else { 
            cout << "NOT Guided Tour : " << typeid(*it).name() << "\n"; 
        }
        //(*it).display();
    }
}

ただし、常にガイド付きツアーのオプションではありません。

4

4 に答える 4

2

マットのリンクを参照:

Base クラスへのポインターを格納することで、スライスが不要になり、目的のポリモーフィック動作も実現できます。

したがって、ベクトルを作成します

list = new vector<Tour*>(); 

それよりも

list = new vector<Tour>(); 
于 2013-08-21T05:39:52.243 に答える
2

上記のコメントが言うように、それはslicingによるものです。参照ポインタではなく にを格納するため、値をコンテナにコピーすると (はい、コピーされます!)、すべてのオブジェクトが基本クラスに切り詰められます。vectorTour

于 2013-08-21T05:40:47.863 に答える
0

おっしゃるとおりスライスがあります。

オブジェクト (基本クラス)をvector格納すると、格納されるTourオブジェクト ( ) のすべての派生オブジェクト固有のメンバーがGuidedTourコピー中にスライスされ、基本クラス オブジェクトとして機能します。

解決策は、基本クラスのポインタを格納することです:

std::vector<Tour*> list;

ポインターを格納しているため、オブジェクトのコピーもオブジェクトのスライスもありません。

これを行う最善の方法はsmart pointers、メモリ管理を手動で行う必要がないように使用することです。

std::vector<std::unique_ptr<Tour>> list;

ただし、スマート ポインターを使用する場合は、std::vector::emplace_back()代わりに以下を使用する必要がありますpush_back

std::vector<std::unique_ptr<Tour>> list;

list.emplace_back(new Tour);
list.emplace_back(new GuidedTour);
list.emplace_back(new Tour);
list.emplace_back(new GuidedTour);
list.emplace_back(new Tour);

実例

しかし、これらの手法は C++11 を使用することを意味します。

于 2013-08-21T07:24:50.973 に答える
0

これはスライスの問題であるという以下の他の回答に同意しますが、リリース時にメモリを管理できるように、unique_ptrs のベクトルにします。私のバージョンの下を参照してください。また、基本クラスに仮想デストラクタを追加しました。これは、基本ポインタを介して派生クラスを参照している場合は常に、基本ポインタを介して破棄する場合のスライスを回避するための良いアイデアです。

#include <iostream>
#include <memory>
#include <vector>

class Tour
{

  public:
  Tour(const std::string& tt, const std::string& desc, double p  ) : tourType_(tt), description_(desc), price_(p){}

  virtual void display () const
  {
    std::cout << "Standard Tour" << std::endl;
  }

  virtual ~Tour() {};

  protected:
  std::string tourType_;
  std::string description_;
  double price_;
};

class GuidedTour : public Tour
{

  public:
  GuidedTour(const std::string& tt, const std::string& desc, double p, const std::string& date, const std::string& name, int age  ) : Tour(tt,desc,p), date_(date), guideName_(name), guideAge_(age) {}


  void display () const 
  {
    std::cout << "Guided Tour" << std::endl;
  }

  private:
  std::string date_;
  std::string guideName_;
  int guideAge_;
};


int main ( int argc, char *argv[] )
{
  std::vector<std::unique_ptr<Tour> > v;

  v.emplace_back(new Tour("FP001", "Fun Park 3 Day Pass", 110.00));
  v.emplace_back(new Tour("BG002", "Botanical Gardens Entry Pass", 30.00));
  v.emplace_back(new GuidedTour("SK003", "Learn to Ski Adventure Tour", 240.00, "28/07/2008", "Zail S", 25));
  v.emplace_back(new Tour("OZ004", "Open Range Zoo Entry Pass", 45.00));
  v.emplace_back(new GuidedTour("AB005", "Abseiling for Beginners Tour", 120.00, "15/07/2008", "Rex P", 35));
  v.emplace_back(new GuidedTour("RA006", "White Water Rafting Tour", 200.00, "22/06/2008", "Clint R", 16));

  for ( auto& i : v )
  {
    i->display();
  }
}
于 2013-08-21T06:36:21.763 に答える