Hi,
I was thinking of writing this post as a reply of Need small example for compile time polymorphism and runtime polymorphism in c++.
But later decided to open this new thread as some expert may want to give some expert opinion on this.
On the above mentioned thread, mike_2000_17 has given some example of c++ static/dynamic polymorphism. I have gave an example of java static polymorphism.
Here is another way to write static polymorphism in C++ using CRTP Idiom.
I have used same classes in this post what we have used in the above thread.
template <typename T>
class Animal{
public:
void makeCry(){
T &self = *static_cast<T *>(this); //CRTP
self.doCry();
}
};
class Dog : public Animal<Dog>{
public:
void doCry() {
std::cout << "Woof Woof!" << std::endl;
};
};
class Cat : public Animal<Cat>{
public:
void doCry() {
std::cout << "Miaou.." << std::endl;
};
};
template <typename T>
void makeCry(T &animal){
animal.makeCry();
}
int main() {
Dog dog;
Cat cat;
makeCry(dog);
makeCry(cat);
return 0;
}
Main benefit of this is:
1) No virtual function, so no vtable. Base class does not need to add any virtual functions. It can help you to add more functionality without changing base class header.
2) static_cast happend on compile time, so minimal runtime overhead.
That is one use case of CRTP Idioms.
Here is another interesting one. Implement one operator in derived class, for example <, and you can have all other operator from Base class.
template <typename T>
class Ordered{
public:
bool operator>=(const T &other){
T &myself = *(static_cast<T *>(this));
return other < (myself);
}
bool operator!=(T &other){
T &myself = *(static_cast<T *>(this));
return (other < myself) && !(myself < other);
}
bool operator==(T &other){
T &myself = *(static_cast<T *>(this));
return !(myself != other);
}
};
/*CuriousCaseOfTemplate is a derived class which just implemented its own < operator. Ordered has injected other operator in it. ;) Look at the main()*/
class CuriousCaseOfTemplate: public Ordered<CuriousCaseOfTemplate>{
int a;
public:
CuriousCaseOfTemplate(int a): a(a){
}
bool operator<(const CuriousCaseOfTemplate &other) const{
return a < other.a;
}
};
int main() {
CuriousCaseOfTemplate a(2), b(4), c(4);
assert(a<b);
assert(b>=a);
assert(b!=a);
assert(b==c);
}
I hope it helps to understand CRTP.