当前位置: 首页 > article >正文

CRTP奇异递归模板模式

文章目录

  • CRTP
  • 基本实现
  • CRTP 的应用
  • 总结

CRTP

运行时多态(动态多态)使用传统继承 + 虚函数,会引入 虚表(vtable),每次调用虚函数都要通过间接寻址,影响性能。
CRTP(Curiously Recurring Template Pattern),即奇异递归模板模式,是一种 C++ 编译期多态技术(静态多态)。它的核心思想是:派生类作为模板参数传递给基类,从而在编译期实现静态多态,避免了运行时的虚函数开销。同时保持接口的可复用性。

基本实现

普通虚函数实现(动态多态):
虚函数(动态多态):interface() 通过 vtable(虚表) 调用 implementation(),运行时解析,有额外的虚函数开销。

class Base {
public:
    virtual void implementation() { std::cout << "Base\n"; }
    void interface() { implementation(); }
    virtual ~Base() = default;
};

class Derived : public Base {
public:
    void implementation() override { std::cout << "Derived\n"; }
};

CRTP 实现(静态多态,消除虚表):
Base< Derived> 是一个 模板基类,但它的模板参数是派生类 Derived 自己。
interface() 里使用 static_cast<Derived*>(this)->implementation();,在编译期解析出正确的implementation(),避免了虚函数的开销。
Derived 继承自 Base< Derived> ,提供 implementation() 方法,实际执行时 直接调用派生类的方法。

#include <iostream>

// CRTP 基类
template <typename Derived>
class Base {
public:
    void interface() {
        // 调用派生类的方法
        static_cast<Derived*>(this)->implementation();
    }
};

// 具体派生类
class Derived : public Base<Derived> {
public:
    void implementation() {
        std::cout << "Derived::implementation()" << std::endl;
    }
};

int main() {
    Derived d;
    d.interface();  // 调用 Derived::implementation()
}

CRTP 的应用

  1. 实现静态计数器
    通过 CRTP 模板参数区分不同类的静态变量,保证 A 和 B 各自维护自己的计数。
template <typename T>
class Counter {
    static int count;
public:
    Counter() { ++count; }
    ~Counter() { --count; }
    static int getCount() { return count; }
};

// 静态变量初始化
template <typename T> int Counter<T>::count = 0;

// 统计不同类对象的数量
class A : public Counter<A> {};
class B : public Counter<B> {};

int main() {
    A a1, a2;
    B b1;
    std::cout << "A count: " << A::getCount() << "\n"; // 2
    std::cout << "B count: " << B::getCount() << "\n"; // 1
}
  1. C++ 标准库 std::enable_shared_from_this< T> 采用了 CRTP,让 MyClass 能够安全地从 this 返回 shared_ptr< T>,避免对象 被错误地 delete 两次。
#include <iostream>
#include <memory>

class MyClass : public std::enable_shared_from_this<MyClass> {
public:
    std::shared_ptr<MyClass> getShared() {
        return shared_from_this();
    }
};

int main() {
    auto ptr = std::make_shared<MyClass>();
    auto sharedPtr = ptr->getShared();
    std::cout << "Reference count: " << sharedPtr.use_count() << "\n"; // 2
}

std::enable_shared_from_this 只是 管理 shared_ptr 生命周期,和 CRTP 静态多态无关。
std::unique_ptr< Base>,建议用传统继承 + 虚函数。

如果想使用CRTP 的静态多态,但又希望能存储不同的子类对象,可以使用 std::variant如下所示:

#include <variant>

template <typename Derived>
class Base {
public:
    void interface() {
        static_cast<Derived*>(this)->implementation();
    }
};

class Derived : public Base<Derived> {
public:
    void implementation() {
        std::cout << "Derived implementation\n";
    }
};

int main() {
    std::variant<Derived> obj = Derived();
    std::visit([](auto& derived) { derived.interface(); }, obj);
}

总结

CRTP(奇异递归模板模式) 是 静态多态 的一种实现方式。
优势:
避免虚函数开销,提高性能。
可以在基类中调用派生类的方法。
模板编程的基础,支持静态计数器、链式调用、策略模式等。
劣势:
代码可读性较低,不适合过于复杂的继承体系。
不支持运行时多态,无法用于 std::unique_ptr< Base>。


http://www.kler.cn/a/589455.html

相关文章:

  • SSM框架——Spring面试题
  • 因果推荐|可解释推荐系统的反事实语言推理
  • Spring Boot 整合 Elasticsearch:打造高性能全文检索实战
  • Mac电脑python 有没有ros接口 查看lidar的数据
  • WEB安全--SQL注入--DNSlog外带
  • 时区转换工具
  • X86 RouterOS 7.18 设置笔记六:端口映射(IPv4、IPv6)及回流问题
  • 无SIM卡时代即将来临?eSIM才是智联未来?
  • 一键批量txt转DWG,DWG转txt——插件实现 CAD c#二次开发
  • 基于Flask的东方财富网股票数据可视化分析系统
  • 基于python的图书馆书目推荐数据分析与可视化-django+spider+vue
  • 直击行业痛点,赛逸展2025科技创新奖推陈出新
  • Flutter_学习记录_ ImagePicker拍照、录制视频、相册选择照片和视频、上传文件
  • PHP:从入门到进阶的编程之旅
  • 语言大模型的模型微调方法LoRA
  • Linux进程状态详解:僵尸进程与孤儿进程的深度探索与实践
  • idea如何新建springboot项目
  • OpenManus:无需邀请码的开源版Manus,开启自动化新纪元
  • 2024山东大学计算机复试上机真题
  • 50个常用的DeepSeek提示词