Say I have a class that can use different types of distance functions (Euclidean distance, etc) to do some comparisons. I have implemented these functions as subclasses of a class Distance:
class Distance;
class EuclideanDistance : public Distance;
class OtherDistance : public Distance;
It seems that to choose which type of distance to use, I could do:
template <typename TDistance>
class MyClass;
and instantiate it with:
MyClass<EuclideanDistance> instance;
or accomplish the same thing with:
class MyClass
{
public:
Distance* myDistanceFunction;
}
and instantiating it with
MyClass instance;
instance.myDistanceFunction = new EuclideanDistance;
are there any advantages of one method over the other?
Thanks,
David
Association (i.e. the solution without templates) is preferable since it offers you more flexibility, allows you to change distance implementation at runtime, generates cleaner error messages and cleaner object files (fewer symbols).
Also, classes generated from the template parametrized with different types (distance implementations) will be considered different types and will not be interchangeable: MyClass<EuclideanDistance>
is a different type than MyClass<MinkowskiDistance>
. This will force you to make all functions that operate on MyClass
templates as well and will ultimately lead to greater complexity with no added benefits.
Templates should be used when you need to relax type-safety of the language, for example when you are writing a class which should operate on a number of unrelated types (not derived from a common base class/interface) which nonetheless behave in a similar manner (e.g. all have a kwak()
member function). This is called duck-typing: types are formally unrelated but all exhibit similar properties.
In case you're prevented from ensuring that all distance implementations derive from a common base class/interface, you may need to use templates. Otherwise, prefer simple and flexible association.
Well, aside from the compile time vs run time issue, the biggest difference has kind of been disallowed by your pre-existing code. Using a template would have allowed you to use any types that supported a common operation (i.e. getDistance) without them having to be from the same heirarchy. This would have meant that Euclidean distance and your other class could have been completely different, yet still useable in the template as long as they supported the subset of members the template made use of.
The former fixes the distance metric for the class at compile-time, while the second does it at run-time. The former is likely more efficient because it allows the compiler to optimize parts of it away, while the second can be more flexible.
Public inheritance means IS-A. Is a EuclideanDisatance interoperable with a "LorentzDistance" or "QuaternionDistance" (or whatever) in any meaningful way? Are they both "distances" in the sense that some code somewhere would be happy to use either one in a non-trivial way (that is, something other than printing the value, etc...)? My guess is no, it's not.
So you want generics, not inheritance. Templates are a simpler promise: two things "look like" each other syntactically.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With