C ++, inheritance versus polymorphism

I have a little "philosophical" question. There is a class A

class A { } 

and classes A1, A2, A3 obtained from A.

 class A1 : public A { } class A2 : public A { } class A3 : public A { } 

and one static method for processing objects A - A3. Which option should be preferred?

 A) class Algorithms { //Object of derived class could be use instead of the object base class public: void test (const A *a) {} }; 

or

 B) class Algorithms { public: //Templatize parameter template <typename TType> void (const TType *a) {} }; 

In my opinion, in this case, option a) is preferable (therefore, the templation is excessive ...)

The parameter b) means that the input can be of any type that has no relation to inheritance to class A.

It will be used when the test () method can work with another type B

 class B { } 

and types A-A3.

Are these conclusions correct or not?

+4
source share
4 answers

The template allows you to do the same with unrelated classes.

You can also use adapters so that you can create adapters for A and B (unbound) that exit the shared adapter and perform the necessary functions.

The main goal of a template is usually to apply the same logic to mostly unrelated types, because, for example, you somehow control sets of types, and the algorithm relates to how you manipulate them.

+1
source

You're right.

To take full advantage of the polymorphism and eliminate redundant code, you should prefer option A. Use option B if you want your method to be available for other classes as well, although even then it is probably better to overload the function rather than using a template.

Say you have two pointers A* a and A1* a1 . If you call your method on both a and a1 , two methods will be created during compilation: one takes the parameter A* , the other takes a A1* . This is useless, since polymorphism can only handle passing the parameter A* .

In addition, there is an advantage that you can separate the implementation from the declaration, which is not possible with templates.

+3
source

Option a seems more convenient in this case when you are done. I would give an answer as your conclusion: "the method of processing the base class will actually process all derived classes and the intention here is suitable for this case."

+1
source

The choice here is not (only) stylistic: option A provides polymorphism at runtime, while option B provides compile-time polymorphism. You have not provided us with enough information to find out which one is preferable in this case.

In general, my advice would be to use parameter A if and only if you want to call test with A* . This leads to the assumption that A is probably an abstract base class (or at least has virtual functions). In this case, it is unsafe to use option B, and, hopefully, test will consist in calling some virtual functions on A* before the desired effect (unlike dynamic_cast this can be done in unpleasant ways).

However, if you never call test with A* , option B is usually better: you allow the use of a function with any type, and calls to virtual functions have less execution time (which may be insignificant, but nonetheless). It also gives the function a bit more freedom: for example, it can create another TType if necessary, which is more difficult if you pass it a pointer to an abstract base class. Finally, you can use features like specialized patterns and static statements if you really want to.

In general, the question should be "Should I use polymorphism at runtime with this class?"; the choice between the two becomes obvious if you decide this.

(By the way, in the case of a template, you probably want to go through TType const& , not TType const* .)

0
source

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


All Articles