奇异递归

奇异递归(Curiously Recurring Template Pattern,CRTP) 是一种C++模板编程技术,其核心思想是:一个类(派生类)将自己作为模板参数传递给其基类。这种模式通过编译时多态(静态多态)实现类似运行时多态的行为,但避免了虚函数的开销。

基本结构

template <typename Derived>
class Base {
    // 基类通过模板参数Derived访问派生类的成员
};

class Derived : public Base<Derived> {  // 派生类将自己作为模板参数传递给基类
    // 派生类实现
};

核心特点

  1. 编译时多态基类通过static_cast<Derived*>(this)直接调用派生类的方法,无需虚函数表(vtable)的开销。
  2. 派生类自我引用派生类继承时,将自己作为模板参数传递给基类模板。

典型用途

1. 静态多态(替代虚函数)

template <typename Derived>
class Animal {
public:
    void Speak() {
        static_cast<Derived*>(this)->ImplementSpeak();
    }
};

class Cat : public Animal<Cat> {
public:
    void ImplementSpeak() { std::cout << "Meow\n"; }
};

class Dog : public Animal<Dog> {
public:
    void ImplementSpeak() { std::cout << "Woof\n"; }
};

// 使用
Animal<Cat> cat;
cat.Speak();  // 输出 "Meow"(编译时绑定)

2. 计数器模式(统计实例数量)

template <typename T>
class Counter {
public:
    static int count;
    Counter() { ++count; }
    ~Counter() { --count; }
};
template <typename T> int Counter<T>::count = 0;

class Widget : public Counter<Widget> {};  // 每个Widget实例自动计数

3. 链式调用(Fluent Interface)

template <typename Derived>
class Chainable {
public:
    Derived& self() { return static_cast<Derived&>(*this); }
    Derived& SetX(int x) { /*...*/ return self(); }
};

class Builder : public Chainable<Builder> {
    // 可链式调用:Builder().SetX(1).SetY(2)
};

优点

  • 性能:避免虚函数调用的运行时开销。
  • 灵活性:基类可对派生类进行编译时定制。
  • 代码复用:通用逻辑集中在基类中。

注意事项

  1. 类型安全:需确保模板参数确实是派生类(可通过static_assert验证)。
  2. 菱形继承:多重继承时可能引发问题。
  3. 可读性:代码可能对初学者较难理解。

与其他技术的对比

虚函数

运行时

较低

需要运行时动态绑定

CRTP

编译时

需要静态多态或代码复用

概念/约束(C++20)

编译时

类型约束和泛型编程

CRTP是C++模板元编程中的经典模式,广泛应用于库设计(如Boost.Iterator、Eigen等),适合需要高性能和编译时确定性的场景。

全部评论

相关推荐

评论
3
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务