Reputation: 4255
I have a little bit "philosophical" question. There is a class A
class A
{
}
and classes A1, A2, A3 derived from A.
class A1 : public A
{
}
class A2 : public A
{
}
class A3 : public A
{
}
and one static method processing objects A - A3. Which variant 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, the option a) is preferable (so the templatization is redundant...)
The option b) means that the input can be any type, that is not in any inheritance relationship to the class A.
It would be used in the case where the method test() can work with another type B
class B
{
}
and types A-A3.
Are these conclusions correct or not?
Upvotes: 4
Views: 1102
Reputation: 3471
The choice here is not (only) a stylistic one: option A provides runtime polymorphism, while option B provides compile-time polymorphism. You have not supplied us with enough information to figure out which one is preferred in this case.
In general, my advice would be to use option A if and only if you want to call test
with an A*
. With this comes the assumption that A
is probably an abstract base class (or at least has virtual functions). In that case it is not even possible to sanely use option B, and hopefully test
will consist of calling some virtual functions on the A*
to a desired effect (as opposed to dynamic_cast
ing it in nasty ways).
However, if you are not ever going to call test
with an A*
, option B is generally better: you allow for the function to be used with any type, and there is less runtime overhead from calling virtual functions (which may be negligible, but none the less). It also gives the function somewhat more freedom: for instance, it can create another TType
if necessary, which is harder if you pass it a pointer to an abstract base class. Finally, you get to use features like template specialisations and static asserts if you really want to.
All in all, the question should be "Do I want to use runtime polymorphism with this class?"; the choice between these two becomes obvious once you decide that.
(By the way, in the case of the template, you probably want to pass TType const&
, not TType const*
.)
Upvotes: 0
Reputation: 31435
The template allows you do to the same things with unrelated classes.
You can also use adapters so you would make adapters for A and for B (unrelated) that derive from a common adapter and perform the functionality you want.
The main purpose of a template normally is to apply the same logic to primarily unrelated types because, for example, you are manipulating collections of types in some way and the algorithm relates to how you manipulate them.
Upvotes: 1
Reputation: 386
Option a seems more convenient in this case as you concluded. I would given an answer as your conclusion: "a method processing the base class will actually process all derived classes and the intention here suits to this case".
Upvotes: 1
Reputation: 258568
You are right.
To fully take advantage of polymorphism and exclude redundant code, option A should be prefered. Use option B if you want your method to also be available for other classes, although even then it's 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 taking a A*
parameter, the other one a A1*
parameter. This is useless, since polymorphism can handle just passing an A*
parameter.
Also, there is the advantage that you can separate the implementation from the declaration, which is not possible in the case of templates.
Upvotes: 3