C ++类型的问题[重复]

Posted

技术标签:

【中文标题】C ++类型的问题[重复]【英文标题】:C++ type of issue [duplicate] 【发布时间】:2013-08-21 05:27:20 【问题描述】:

Tour 和 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();
    

但它总是返回 NOT 导游选项。

【问题讨论】:

【参考方案1】:

参考 Mat 的链接:

通过存储指向基类的指针,就不会进行切片,您也可以实现所需的多态行为

所以创建一个向量

list = new vector<Tour*>(); 

而不是

list = new vector<Tour>(); 

【讨论】:

【参考方案2】:

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

【讨论】:

【参考方案3】:

我同意下面的其他答案,即这是一个切片问题,尽管我会将其设为 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();
  

【讨论】:

我用的是C++98,所以不能用这个:(【参考方案4】:

就像说的那样,有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。

【讨论】:

我用的是c++98所以不能用这个 @Archie 好的。但是,一开始std::vector&lt;Tour*&gt; list; 的方法仍然有效:)

以上是关于C ++类型的问题[重复]的主要内容,如果未能解决你的问题,请参考以下文章

如何在c ++中删除嵌套列表中的重复元素

C ++函数返回不同的数据类型[重复]

循环中的C ++对象引用[重复]

C ++继承类型[重复]

c语言的问题!!急!!

C#打开类型[重复]