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>
{
    // ...
};

目的是啥呢?主要解決的是虛函數實現的多態效率低下的問題,繼承層次多了,虛函數這種動態實現多態的機制效率低下,資源浪費嚴重。this

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",模擬的動態綁定。指針

傳統的多態是這樣的,使用基類指針指向實例化後的子類,經過虛函數實現多態。code

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)上代碼:ip

// 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_patternrem

相關文章
相關標籤/搜索