This is best described in pseudo-code:
class Thing {};
interface ThingGetter<T extends Thing> {
T getThing();
}
class Product extends Thing {};
class ProductGetter<Product> {
Product getThing() {
// Some product code
}
}
class SpecialProductGetter extends ProductGetter {
Product getThing() {
p = ProductGetter::getThing();
// Do some special stuff;
return p;
}
}
class NeatProductGetter extends ProductGetter {
Product getThing() {
p = ProductGetter::getThing();
// Do some neat stuff;
return p;
}
}
I will have other “things” with other getters for those as well.
I’ve tried codifying this in C++ but it doesn’t like :
template <> class ThingGetter <Product> {
nor:
class NeatProductGetter : public ThingGetter <Product> {
- Can you model this in C++ without making getThing return a
Thingand then having to cast it like crazy? - If so, how? If not, what is the best way to do this?
Thanks!
Since the question comes from someone with a Java background, I will interpret it in Java terms. You want to define a generic interface that will return an object derived from T:
Note the changes: the function is declared virtual so that it will behave polimorphically in derived objects. The return value is a pointer instead of an object. If you keep an object in your interface, the compiler will slice (cut the non-base part of the returned object) the return. With some metaprogramming magic (or resorting to boost) you can have the compiler test the constraint that T derives from a given type.
Now the question is why you would like to do so… If you define a non-generic interface (abstract class) that returns a Thing by pointer you can just get the same semantics more easily:
The compiler will require all instantiable classes derived from getter to implement a get() method that returns a Thing by pointer (or a covariant return type: pointer to a class derived from Thing). If the derived class tries to return another type the compiler will flag it as an error.
The problem, as you post it is that if you use the interface, then the objects can only be handled as pointers to the base Thing class. Now, whether that is a problem or not is another question… In general, if you have correctly designed your hierarchy, you should be able to use the returned objects polimorphically without having to resort to down casting.
Note that if you are using the different getters at the most derived level in the hierarchy, each
get()method returns the most derived element from the Thing hierarchy, at that point you will not need to down cast at all. Only if you use the different getters through the basegetterinterface you will get the same return type for all (Thing*)It is important to note that templates are resolved completely at compile time. That means that trying to use templates to solve the need (do you really need it?) to downcast will not help you if you use the different getters through the interface (reference/pointers to the basic getter).
Maybe posting a little more details on your specific domain, where and how you intend to use this code, can help in providing more useful responses.