这篇文章介绍了什么是CRTP(奇异的递归模板模式)
原文
stackflow上讨论了CRTP
问题
我的理解
- 简而言之,就是基类是个模板类,模板参数是基类类型。
template <class T>
class X{...};
class A : public X<A> {...};
- 它的存在是为了实现多态或者是一种类似多态功能。我觉得这不是CRTP的本意。例子如下:
>```c++
template<typename T>
class Base
{
public:
void method()
{
static_cast<T*>(this)->methodImpl();
}
private:
void methodImpl()
{
cout << "base method" << endl;
}
};
class Extend1 :public Base<Extend1>
{
public:
void methodImpl()
{
cout << "Extend1 method" << endl;
}
};
class Extend2 :public Base<Extend2>
{
public:
void methodImpl()
{
cout << "Extend2 method" << endl;
}
};
void main()
{
Extend1 e1;
Extend2 e2;
e1.method();
e2.method();
}
网上好多说法是这体现了CRTP的静态绑定,性能优于虚函数实现的动态绑定。其实这根本不能体现多态。多态是由基类对象通过虚函数表,实现的对不同子类函数的调用。
- CRPT其实是让子类获取基类能力的方法,并且子类中不需要添加任何代码。也就是说,基类是一个功能模板,只要被继承,子类就获得其功能。例子:
//单例模式基类
class Singleton
{
public:
static ActualClass& GetInstance()
{
if(p == nullptr)
p = new ActualClass;
return p;
}
protected:
static Actualclass p;
private:
Singleton(){}
Singleton(Singleton const &);
Singleton& operator = (Singleton const &);
};
template <class T>
T* Singleton<T>::p = nullptr;
//子类也是一个单例模式类
class A: public Singleton<A>
{
//Rest of functionality
};
```c++
template<class Derived>
//基类类实现== != >等操作 派生类只需要实现<操作
class Equality
{
};
template <class Derived>
bool operator == (Equality<Derived> const& op1, Equality<Derived> const & op2)
{
Derived const& d1 = static_cast<Derived const&>(op1);//you assume this works
//because you know that the dynamic type will actually be your template parameter.
//wonderful, isnit it?
Derived const& d2 = static_cast<Derived const&>(op2);
return !(d1 < d2) && !(d2 < d1);//assuming derived has operator <
}
//只要派生类继承Equality 就能实现其他三个操作 大大减少了代码量
struct Apple:public Equality<Apple>
{
int size;
};
bool operator < (Apple const & a1, Apple const& a2)
{
return a1.size < a2.size;
}
int main()
{
Apple a1;
Apple a2;
a1.size = 10;
a2.size = 10;
if(a1 == a2) //the compiler won't complain!
{
}
}
- 通过这些例子,可以看出CRPT是一种非常有效的减少代码量的手段,能够快速让子类获取自身能力,而不新增任何代码。至于它的静态多态,我认为是不合理的。