LiSheng's blog LiSheng's blog
首页
笔记
个人简历
随笔集
GitHub (opens new window)
首页
笔记
个人简历
随笔集
GitHub (opens new window)
  • golang

  • cplus

    • 内存相关

    • 面向对象

      • 相关问题
      • 构造、析构顺序
      • 对象内存布局
      • 静态、动态多态
      • 虚函数表
      • 重载、重写、覆盖
      • 构造函数不能是虚函数
      • CRTP模式的原理和用途
        • 移动语义move
        • 构造函数初始化列表
        • 静态成员变量和函数
        • 多重继承
        • 菱形问题与虚继承
        • 对象池
      • STL相关

      • 内置数据结构
      • 数据结构示例
      • go和c++对比
      • 关键字

    • leetcode

    • 存储技术

    • 分布式系统

    • 计算机网络

    • Linux操作系统

    • Redis

    • 其他

    • 笔记
    • cplus
    • 面向对象
    lisheng
    2024-09-10
    目录

    CRTP模式的原理和用途

    CRTP(Curiously Recurring Template Pattern),又称为奇异递归模板模式,是C++中的一种高级编程技术,它涉及到模板类的递归继承。CRTP的核心思想是让一个类派生自一个以自己作为模板参数的模板类,从而实现一些特殊的设计模式和编译时多态性。

    # 一、CRTP的基本原理

    CRTP模式的基本形式如下:

    template <typename Derived>
    class Base {
    public:
        void interface() {
            // 调用派生类实现的实现细节方法
            static_cast<Derived*>(this)->implementation();
        }
    
        void implementation() {
            // 可以提供一个默认实现,但派生类通常会覆盖它
            std::cout << "Base implementation\n";
        }
    };
    
    class Derived : public Base<Derived> {
    public:
        void implementation() {
            std::cout << "Derived implementation\n";
        }
    };
    
    int main() {
        Derived d;
        d.interface(); // 调用的是 Derived::implementation
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25

    # 二、CRTP的工作机制

    在CRTP中,基类 Base 是一个模板类,它接受派生类 Derived 作为模板参数。派生类 Derived 继承自以自己为模板参数的 Base,即 Base<Derived>。这意味着在编译时,Base 已经知道它的派生类 Derived,并且可以在基类中通过 static_cast 将自己转换为派生类,从而调用派生类的实现。

    # 三、CRTP的用途

    CRTP在C++中有多种用途,常见的包括:

    1. 编译时多态性

      • CRTP可以在编译时实现类似于动态多态的行为,但没有运行时的开销。通过CRTP,基类可以在编译时调用派生类的方法,而不需要使用虚函数表。
      • 这对于性能要求高的场合特别有用,因为它避免了运行时多态性带来的额外开销。
    2. 静态多态

      • CRTP可以实现静态多态,即在编译时确定调用的具体函数,而不是在运行时。这使得编译器可以进行更好的优化。
      • 例如,使用CRTP可以创建一个接口类,所有派生类都需要实现该接口的方法,但这些方法调用在编译时已经被确定,不需要虚函数表。
    3. 代码复用

      • CRTP允许基类中的通用代码与派生类中的特定实现相结合,增强了代码复用性。
      • 通过CRTP,开发者可以在基类中实现一些通用的逻辑,而将特定的行为留给派生类来定义。
    4. 模版元编程

      • CRTP可以与模板元编程技术结合,用于编写复杂的编译时逻辑,比如创建类型列表、类型操作等。

    # 四、CRTP对对象行为的影响

    1. 避免虚函数的运行时开销

      • CRTP通过在编译时确定函数调用,避免了虚函数的动态分派,因此没有虚函数表(vtable)和虚函数表指针(vptr)的开销。
    2. 编译时检查

      • 由于CRTP是在编译时处理的,编译器可以在编译期捕获错误,而不是在运行时。这提高了类型安全性和代码的健壮性。
    3. 增加代码复杂性

      • CRTP的一个潜在问题是增加了代码的复杂性,尤其是对于不熟悉模板编程的开发者而言,代码的可读性可能受到影响。
    4. 静态多态的局限性

      • 尽管CRTP提供了编译时的多态性,但它无法完全替代运行时多态性。在某些情况下,如果需要真正的动态多态性(如在运行时决定调用哪个派生类的方法),仍然需要使用虚函数。

    # 五、CRTP的示例:策略模式

    CRTP可以用来实现策略模式,其中策略的选择是在编译时完成的。

    template <typename T>
    class Sorter {
    public:
        void sort() {
            static_cast<T*>(this)->sort_impl();
        }
    };
    
    class QuickSort : public Sorter<QuickSort> {
    public:
        void sort_impl() {
            std::cout << "QuickSort algorithm\n";
        }
    };
    
    class MergeSort : public Sorter<MergeSort> {
    public:
        void sort_impl() {
            std::cout << "MergeSort algorithm\n";
        }
    };
    
    int main() {
        QuickSort qs;
        qs.sort(); // Output: QuickSort algorithm
    
        MergeSort ms;
        ms.sort(); // Output: MergeSort algorithm
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29

    在这个例子中,Sorter 是一个基类模板,QuickSort 和 MergeSort 是具体的排序策略,它们在编译时就已经确定使用哪种排序算法。

    # 总结

    CRTP模式是一种强大的C++编程技巧,通过让派生类继承自以自身为模板参数的基类,实现编译时多态、代码复用和高效的静态接口。它适用于需要编译时确定行为的场景,但也要求开发者对模板编程有一定的理解。通过CRTP,C++程序员可以在性能与灵活性之间找到良好的平衡。

    编辑 (opens new window)
    上次更新: 2024/09/13, 11:59:12
    构造函数不能是虚函数
    移动语义move

    ← 构造函数不能是虚函数 移动语义move→

    最近更新
    01
    ceph分布式存储-对象存储(RGW)搭建
    10-27
    02
    ceph分布式存储-集群客户端连接
    10-27
    03
    ceph分布式存储-管理crushmap
    10-27
    更多文章>
    Theme by Vdoing
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式