Polymorphic return types in C ++

I saw several posts on this issue, but not something that summarizes all the parameters that I have in my current situation, and there may be solutions that I have not considered.

My situation is pretty general. I have a couple of Inf1 Inf2 classes (which are more like interfaces) have pure virtual methods.

Where Inf1 has a method

(Inf2& or Inf2* or shared_pointer) foo(/** Some info on how to build the object**/) = 0

(this is part of the problem).

In Inf1 implementations, various Inf2 implementations are Inf2 when implementing foo .

Inf2 implementations Inf2 relatively small, so I would not want to return them by value, so that they are copied with the result, but I can not declare foo to return only Inf2 , because then I return the abstract object.

Any preferred and or creative ways to solve this problem? :)

+4
source share
2 answers

So, you have types Inf1 and Inf2 that are related to each other, and at least one of them contains abstract methods.

You want to return some sub-implementation of Inf2 , but which one is determined at runtime.

This means that you need runtime polymorphism. There are three different ways you could approach this.

First, you can return a pointer - perhaps a smart pointer, such as unique_ptr , to a common interface. This requires free storage (heap), but it becomes clear, and this is the simplest answer.

Secondly, you can write an erasure object of type that provides a virtual version of non- virtual , and forwards some internal details. These internal details will ultimately use some kind of smart pointer or a third solution. The advantage here is that you can hide how you manage memory and just expose the semantics of value with a cheap move. The disadvantage is that there are many templates.

Thirdly, you can use something like boost::variant - a union for a set of types with means of protection against access to incorrect types. While boost cannot be used directly, the design can be simulated. The idea is that you have local storage in which you place new data, except, perhaps, for larger objects, where instead you use a smart pointer. Unlike the second solution, the set of supported types is explicitly specified in your type. This is the most difficult decision (if you do not have access to boost ) and requires that you have a fixed (at compile time) set of Inf2 implementations that all Inf1 users should have full information about.

As already noted, the first solution is the simplest. The costs of the first solution are based only on performance, and these performance results will not be difficult to fix after that fact, if you find them where there are real problems. Therefore, I would advise solution No. 1, and then a profile, to find out if the costs are too high. If the costs are high, go to Solution # 3, possibly into the shell of Solution # 2.

+3
source

Your question really relates to memory management. Polymorphic subclasses of Inf2 can be arbitrarily large, and the largest are not known at compile time, therefore you cannot store them with automatic storage time, therefore they cannot be returned by value - therefore you need to manage the memory for them somehow at least through return

Where are Inf2 subclass objects Inf2 ? And when and where will the Inf2 implementations be removed. The answer to this usually determines which descriptor concept to use. For example, if you allocate Inf2 implementations in a memory pool, then returning Inf2* fine. You can also use unique_ptr<Inf2> if you want to make one ownership, but then you cannot copy the handle. You can also use shared_ptr<Inf2> if you want to copy handles, but you have to be careful with loops, and this is a little less efficient. You can also create an Inf2Handle wrapper Inf2Handle that will do something more complex, such as copy to write or other things.

You mentioned that the implementations are small, so perhaps the memory pool is the best architecture.

Which best choice really depends on the bigger picture of how Inf1 and Inf2 should be used.

+2
source

Source: https://habr.com/ru/post/1499114/


All Articles