C++编程模式CRTP

CRTP ,curiously recurring template pattern 神奇的复发模板范式,recurring实在不好翻译,没有合适的词汇,意思是继承的父类是个模板类,参数是自己。上代码看一下吧:

// The Curiously Recurring Template Pattern (CRTP)
template<class T>
class Base
{
    // methods within Base can use template to access members of Derived
};
class Derived : public Base<Derived>
{
    // ...
};

目的是啥呢?主要解决的是虚函数实现的多态效率低下的问题,继承层次多了,虚函数这种动态实现多态的机制效率低下,资源浪费严重。

CRTP用法一,实现静态多态(Static polymorphism),上代码:

template <class Derived>
struct base
{
    void interface()
    {
         // ...
         static_cast<Derived*>(this)->implementation();
         // ...
    }
};

struct derived : base<derived>
{
     void implementation()
     {
         // ...
     }
};

模板带来的好处是,只有Base<Derived>::implementation()使用时,静态函数才实例出来。这种用法有时被称为"simulated dynamic binding",模拟的动态绑定。

传统的多态是这样的,使用基类指针指向实例化后的子类,通过虚函数实现多态。

class Base
{
public:
    virtual void method() { std::cout << "Base"; }
    virtual ~Base() {}
};

class Derived : public Base
{
public:
    virtual void method() { std::cout << "Derived"; }
};

int main()
{
    Base *pBase = new Derived;
    pBase->method(); //outputs "Derived"
    delete pBase;
    return 0;
}

CRTP用法二,对象计数(Object counter),记录一个类被创建和销毁的次数,上代码:

template <typename T>
struct counter
{
    static int objects_created;
    static int objects_alive;

    counter()
    {
        ++objects_created;
        ++objects_alive;
    }
    
    counter(const counter&)
    {
        ++objects_created;
        ++objects_alive;
    }
protected:
    ~counter() // objects should never be removed through pointers of this type
    {
        --objects_alive;
    }
};
template <typename T> int counter<T>::objects_created( 0 );
template <typename T> int counter<T>::objects_alive( 0 );

class X : counter<X>
{
    // ...
};

class Y : counter<Y>
{
    // ...
};

能够对X和Y类分开计数,只能用模板实现,普通的继承基类无法实现。

CRTP用法三,多态拷贝构造(Polymorphic copy construction)上代码:

// Base class has a pure virtual function for cloning
class Shape {
public:
    virtual ~Shape() {};
    virtual Shape *clone() const = 0;
};
// This CRTP class implements clone() for Derived
template <typename Derived>
class Shape_CRTP : public Shape {
public:
    virtual Shape *clone() const {
        return new Derived(static_cast<Derived const&>(*this));
    }
};

// Nice macro which ensures correct CRTP usage
#define Derive_Shape_CRTP(Type) class Type: public Shape_CRTP<Type>

// Every derived class inherits from Shape_CRTP instead of Shape
Derive_Shape_CRTP(Square) {};
Derive_Shape_CRTP(Circle) {};

传统的实现方式是,基类有个虚拟clone函数,每个继承类实现自己的clone函数功能。依靠CRTP技术,只定义一个就够了,大家通用。

资料来源:https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern

赞 (0) 评论 分享 ()