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<Tour*> list;
的方法仍然有效:)以上是关于C ++类型的问题[重复]的主要内容,如果未能解决你的问题,请参考以下文章