The difference between choosing a subclass using a template parameter or instantiating a member variable

Let's say I have a class that can use different types of distance functions (Euclidean distance, etc.) to perform some comparisons. I implemented these functions as subclasses of the Distance class:

class Distance; class EuclideanDistance : public Distance; class OtherDistance : public Distance; 

It seems that to select which type of distance to use, I could do:

 template <typename TDistance> class MyClass; 

and create it with:

 MyClass<EuclideanDistance> instance; 

or do the same thing:

 class MyClass { public: Distance* myDistanceFunction; } 

and creating it with

 MyClass instance; instance.myDistanceFunction = new EuclideanDistance; 

Are there any advantages of one method over another?

Thanks,

David

+8
c ++
source share
4 answers

Association (i.e. a solution without templates) is preferable, as it offers you more flexibility, allows you to change the implementation of the distance at run time, generates error messages and cleaner object files (fewer characters).

In addition, classes created from a template parameterized by different types (distance implementation) will be considered different types and will not be interchangeable: MyClass<EuclideanDistance> is a different type than MyClass<MinkowskiDistance> . This will force you to do all the functions that work with MyClass templates, and also ultimately lead to more complexity without any additional benefits.

Templates should be used when you need to weaken the type safety of a language, for example, when you write a class that should work with several types of unrelated (not derived from a common base class / interface), which nevertheless behave in a similar way (for example, all have a member function kwak() ). This is called duck-typing : types are not formally related to each other, but they all have similar properties.

In case you cannot guarantee that all distance implementations will be obtained from a common base class / interface, you may need to use templates. Otherwise, a simple and flexible association is preferred.

+6
source share

Well, apart from compilation time and runtime, the biggest difference was rejected by your previous code. Using a template would allow you to use any types that support a common operation (i.e. GetDistance), without having to have the same hierarchy. This would mean that the Euclidean distance and your other class could be completely different, but still usable in the template if they supported the subset of members that the template used.

+4
source share

The first captures the distance metric for the class at compile time, and the second at runtime. The first one is most likely more efficient because it allows the compiler to optimize parts of it, while the second one can be more flexible.

+2
source share

Open inheritance means IS-A. Is Euclidean dysfunctional interaction compatible with LorentzDistance or QuaternionDistance (or something else) in any meaningful way? Are they “distances” in the sense that some code somewhere would be happy to use one of them in a non-trivial way (that is, something other than printing the value, etc.)? I think not, it is not.

So you need generics, not inheritance. Templates are a simpler promise: two things are “similar” to each other syntactically.

+1
source share

All Articles