C ++类型的问题

时间:2013-08-21 05:27:20

标签: c++ types casting

Tour and GuidedTour。 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 个答案:

答案 0 :(得分:2)

参考Mat的链接:

通过存储指向Base类的指针,就没有切片,你也可以实现所需的多态行为

所以创建一个

的向量
list = new vector<Tour*>(); 

而不是

list = new vector<Tour>(); 

答案 1 :(得分:2)

正如上面的评论所说,这是因为切片。由于您将存储在vector,而不是引用指针中,因此当您复制时容器中的值(是的,它们被复制了!),然后每个对象都被截断到基类Tour

答案 2 :(得分: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();
  }
}

答案 3 :(得分:0)

就像它说的那样,有Slicing

当您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);

Live example

但这些技术意味着使用C ++ 11。