#include <iostream>
template <class Derived>
class Base
{
public:
void method1()
{
static_cast<Derived*>(this)->method1();
}
void method2()
{
static_cast<Derived*>(this)->method2();
}
};
class Derived1: public Base<Derived1>
{
public:
void method1()
{
std::cout << "Method 1 of Derived1 executed.\n";
}
};
int main(int argc, char *argv[])
{
Derived1 d1;
d1.method1();
d1.method2();
return 0;
}
跟进问题:如何使这种类型安全?也就是说,如果有人忘记实现method2,我希望编译器能够捕获它。我不想让它在运行时爆炸。
答案 0 :(得分:8)
我认为这是有效的原因是如果你实例化这段代码:
void method2()
{
static_cast<Derived*>(this)->method2();
}
其中Derived
没有method2()
的实现,本质上是一个美化的自我递归调用。这里的原因是在Derived1
中,确实存在一个名为method2
的成员函数,即从基类继承的成员函数。
我尝试运行此代码,确实调用method2
导致自递归导致堆栈溢出。
通常,CRTP通过不让基类函数调用同名的派生类函数来避免这种情况。这样,如果派生类缺少特定函数,则调用会触发编译器错误。在您的情况下,这不会发生,因为函数本身可以从基类间接引用。
答案 1 :(得分:2)
Derived1 d1;
d1.method2();
即使Derived1
没有定义method2()
,它仍会通过继承Base
来获取它。这就是它编译和运行的原因。 d1.method2()
实际上会调用Base::method2()
,它再次调用自己。这是递归电话。