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

【QA】CRTP在模板中有哪些用处?

CRTP(Curiously Recurring Template Pattern)即奇异递归模板模式,是 C++ 中的一种模板编程技术,它允许派生类将自身作为模板参数传递给基类。下面详细介绍 CRTP 技术在模板中的用途。

1. 静态多态

在传统的多态实现中,通常使用虚函数来实现动态多态,这会带来一定的运行时开销(如虚函数表查找)。而 CRTP 可以实现静态多态,避免了运行时开销,在编译期就确定调用的函数。

示例代码

cpp

#include <iostream>

// 基类模板
template <typename Derived>
class Base {
public:
    void doSomething() {
        // 调用派生类的具体实现
        static_cast<Derived*>(this)->implementation();
    }
};

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

int main() {
    Derived d;
    d.doSomething();
    return 0;
}
解释

在上述代码中,Base 是一个基类模板,它通过 static_cast 将 this 指针转换为派生类 Derived 的指针,从而调用派生类的 implementation 函数。这种方式在编译期就确定了函数调用,避免了虚函数带来的运行时开销。

2. 代码复用

CRTP 可以让基类为派生类提供一些通用的功能,派生类可以复用这些功能,同时还能根据自身需求进行定制。

示例代码

cpp

#include <iostream>

// 基类模板,提供计数功能
template <typename Derived>
class Counter {
public:
    static int objectCount;

    Counter() {
        ++objectCount;
    }
    ~Counter() {
        --objectCount;
    }

    static int getObjectCount() {
        return objectCount;
    }
};

template <typename Derived>
int Counter<Derived>::objectCount = 0;

// 派生类
class MyClass : public Counter<MyClass> {};

int main() {
    MyClass obj1;
    MyClass obj2;
    std::cout << "Number of MyClass objects: " << MyClass::getObjectCount() << std::endl;
    return 0;
}
解释

在这个例子中,Counter 基类模板为派生类提供了对象计数的功能。MyClass 继承自 Counter<MyClass>,可以复用 Counter 提供的计数功能,而不需要在每个派生类中重复实现。

3. 实现编译期策略模式

CRTP 可以用于实现编译期的策略模式,允许在编译时选择不同的算法或行为。

示例代码

cpp

#include <iostream>

// 策略基类模板
template <typename Strategy>
class Algorithm {
public:
    void execute() {
        static_cast<Strategy*>(this)->algorithm();
    }
};

// 具体策略类 1
class StrategyA : public Algorithm<StrategyA> {
public:
    void algorithm() {
        std::cout << "Executing Strategy A" << std::endl;
    }
};

// 具体策略类 2
class StrategyB : public Algorithm<StrategyB> {
public:
    void algorithm() {
        std::cout << "Executing Strategy B" << std::endl;
    }
};

int main() {
    StrategyA a;
    a.execute();

    StrategyB b;
    b.execute();

    return 0;
}
解释

在这个示例中,Algorithm 是一个基类模板,它通过 CRTP 调用派生类的 algorithm 函数。StrategyA 和 StrategyB 是具体的策略类,它们实现了不同的算法。在编译时,根据选择的派生类来确定执行的具体算法。

4. 扩展类的功能

可以通过基类模板为派生类添加额外的功能,而不需要修改派生类的代码。

示例代码

cpp

#include <iostream>

// 基类模板,为派生类添加打印功能
template <typename Derived>
class Printable {
public:
    void print() {
        std::cout << static_cast<Derived*>(this)->toString() << std::endl;
    }
};

// 派生类
class MyData : public Printable<MyData> {
private:
    int value;
public:
    MyData(int v) : value(v) {}
    std::string toString() {
        return "MyData: " + std::to_string(value);
    }
};

int main() {
    MyData data(42);
    data.print();
    return 0;
}
解释

在这个例子中,Printable 基类模板为派生类 MyData 添加了 print 功能,MyData 只需要实现 toString 函数即可使用这个功能,而不需要在 MyData 类中显式定义 print 函数。

综上所述,CRTP 技术在模板编程中非常有用,它可以实现静态多态、代码复用、编译期策略模式以及扩展类的功能等,同时避免了动态多态带来的运行时开销。


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

相关文章:

  • Ollama + Open WebUI 本地部署DeepSeek
  • test_cases测试用例层/test_1_login
  • 2023 CSP-J 题解
  • 蓝桥杯练习day2:执行操作后的变化量
  • redis分布式锁实现Redisson+redlock中watch dog是如何判断当前线程是否持有锁进行续租的呢?
  • 事务隔离级别是?
  • kotlin 中的构造函数的作用
  • 黑盒问题的操作优化
  • TPAMI-2025 | 中山大学具身导航参数高效训练!NavCoT:通过解耦推理提升基于大模型的视觉语言导航
  • Python列表1
  • hexo+git pages搭建网站避坑QAQ
  • 基于BCLinux制作Apache HTTPD 2.4.63 的RPM安装包
  • JAVA-多线程join()等待一个线程
  • 精细护理:为进行性核上性麻痹患者筑牢生活防线
  • stm32第七天震动传感器
  • NLP高频面试题(四)——BN和LN的区别与联系,为什么attention要用LN
  • 五、AIGC大模型_09手动实现ReAct_Agent
  • linux /bin/bash丢失修复
  • Mac:Maven 下载+安装+环境配置(详细讲解)
  • 动态规划合集——动态规划基本原理