简体   繁体   English

使用抽象类作为模板类型

[英]Using abstract class as a template type

I'm still pretty new to c++ (coming over from java). 我仍然是c ++的新手(来自java)。 I have a stl list of type Actor . 我有一个类型为Actor的stl列表。 When Actor only contained "real" methods there was no problem. Actor只包含“真实”方法时,没有问题。 I now want to extend this class to several classes, and have a need to change some methods to be abstract, since they don't make sense as concrete anymore. 我现在想要将这个类扩展到几个类,并且需要将一些方法改为抽象,因为它们不再具体。

As I expected (from the documentation) this is bad news because you can no longer instantiate Actor , and so when I iterate through my list I run into problems. 正如我所料(从文档中)这是坏消息,因为你不能再实例化Actor ,所以当我遍历我的列表时,我遇到了问题。

What is the c++ way to do this? c ++的方法是什么?

Sorry if there's anything unclear 对不起,如果有什么不清楚的话

You can not handle this directly: 你不能直接处理这个:

As you can see when the class is abstract you can not instanciate the object. 正如您所看到的,当类是抽象的时,您无法实例化该对象。
Even if the class where not abstract you would not be able to put derived objects into the list because of the slicing problem. 即使不抽象的类,由于切片问题,也无法将派生对象放入列表中。
The solution is to use pointers. 解决方案是使用指针。

So the first question is who owns the pointer (it is the responcability of the owner to delete it when its life time is over). 所以第一个问题是谁拥有指针(所有者的响应能力是在其生命周期结束时删除它)。

With a std::list<> the list took ownership by creating a copy of the object and taking ownership of the copy. 使用std :: list <>,列表通过创建对象的副本并获取副本的所有权来获得所有权。 But the destructor of a pointer does nothing. 但是指针的析构函数什么都不做。 You need to manually call the delete on a pointer to get the destructor of the obejct to activate. 您需要手动调用指针上的delete来获取要激活的obejct的析构函数。 So std::list<> is not a good option for holding pointers when it also needs to take ownership. 所以当std :: list <>需要占有权时,它不是保持指针的好选择。

Solution 1: 解决方案1:

// Objects are owned by the scope, the list just holds apointer.
ActorD1   a1; Actor D1 derived from Actor
ActorD2   a2;
ActorD2   a3;

std::list<Actor*>  actorList;
actorList.push_back(&a1);
actorList.push_back(&a2);
actorList.push_back(&a3);

This works fine as the list will go out of scope then the objects everything works fine. 这工作正常,因为列表将超出范围,然后对象一切正常。 But this is not very useful for dynamically (run-time) created objects. 但这对动态(运行时)创建的对象不是很有用。

Solution 2: 解决方案2:

Boost provides a set of containers that handle pointers. Boost提供了一组处理指针的容器。 You give ownership of the pointer to the container and the object is destroyed by the containter when the container goes out ofd scope. 您赋予容器指针的所有权,当容器超出范围时,容器会破坏对象。

boost::ptr_list<Actor>  actorList;

actorList.push_back(new ActorD1);
actorList.push_back(new ActorD2);
actorList.push_back(new ActorD2);

It's not possible to create a std::list<Actor> if the type Actor is abstract. 如果Actor类型是抽象的,则无法创建std::list<Actor> Under the hood a list will hold an instance of the type specified in the template arguments. 在引擎盖下,列表将包含模板参数中指定类型的实例。 Because you can't ever have an instance of an abstract class this won't ever work. 因为你不可能拥有抽象类的实例,所以这不会起作用。

What you can do though is use a level of indirection like a pointer. 你可以做的是使用像指针一样的间接级别。 It is legal to have an instance of a pointer to an abstract class and hence legal to make a stl::list<Actor*> . 拥有一个指向抽象类的指针的实例是合法的,因此合法地创建一个stl::list<Actor*>

STL containers are designed for copyable types. STL容器专为可复制类型而设计。 You should look into Boost pointer containers and/or smart pointers for storing polymorphic type instances in a collection. 您应该查看Boost 指针容器和/或智能指针,以便在集合中存储多态类型实例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM