Using an abstract class as a template type

I'm still pretty new to C ++ (migrating from java). I have a stl list of type Actor . When Actor contained only "real" methods, there were no problems. Now I want to extend this class to several classes and change some methods as abstract, since they no longer make sense as concrete.

As I expected (from the documentation), this is bad news, because you can no longer instantiate Actor , and so when I repeat my list, I have problems.

What is the C ++ way to do this?

Sorry if something is unclear

+4
source share
3 answers

You cannot handle this directly:

As you can see, when a class is abstract, you cannot initiate an object.
Even if the class is not abstract, you will not be able to put derived objects in the list due to a slicing problem.
The solution is to use pointers.

So, the first question is: who owns the pointer (is the owner’s ability to remove it when its lifetime expires).

With std :: list <> the list took responsibility by creating a copy of the object and obtaining ownership of the copy. But the pointer destructor does nothing. You need to manually call delete on the pointer to activate the obejct destructor. Thus, std :: list <> is not a good option for holding pointers when it also needs to take responsibility.

Solution 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 great because the list is out of scope, then all objects work fine. But this is not very useful for dynamically created objects (runtime).

Solution 2:

Boost provides a set of containers that handle pointers. You give ownership of the pointer to the container, and the object is destroyed using the container when the container leaves the area.

 boost::ptr_list<Actor> actorList; actorList.push_back(new ActorD1); actorList.push_back(new ActorD2); actorList.push_back(new ActorD2); 
+6
source

It is not possible to create std::list<Actor> if the Actor type is abstract. Under the hood, the list will contain an instance of the type specified in the template arguments. Since you will never have an instance of an abstract class, this will never work.

What you can do is use the level of indirection as a pointer. It is appropriate to have an instance of a pointer to an abstract class, and therefore it is legal to make a stl::list<Actor*> .

+2
source

STL containers are for copying types. You should examine Boost pointer containers and / or smart pointers to store instances of the polymorphic type in the collection.

+2
source

All Articles