3
#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;
}

后续问题:如何使这种类型安全?也就是说,如果有人忘记实现方法 2,我希望编译器能够捕捉到它。我不希望它在运行时爆炸。

4

2 回答 2

8

我认为这是有效的原因是,如果您实例化此代码:

void method2()
{
  static_cast<Derived*>(this)->method2();
}

whereDerived没有实现method2()将本质上是一个美化的自递归调用。这里的原因是,在 中Derived1,确实有一个成员函数叫做method2,也就是继承自基类的成员函数。

我尝试运行这段代码,果然调用method2导致自递归堆栈溢出。

通常,CRTP 通过不让基类函数调用同名的派生类函数来避免这种情况。这样,如果派生类缺少特定函数,调用会触发编译器错误。在您的情况下,这不会发生,因为函数本身可以从基类间接引用。

于 2011-01-18T06:23:10.603 回答
2
  Derived1 d1;
  d1.method2();

即使Derived1没有定义method2(),它还是通过继承来获得它Base。这就是它编译和运行的原因。d1.method2()实际上调用Base::method2(),它再次调用自己。这是一个递归调用。

于 2011-01-18T06:23:16.703 回答