天天看點

C++ 慣用法之 CRTP

背景

CRTP 是 一種 C++ 的設計方法,其巧妙的結合了繼承和模闆程式設計技術,可以用來給類提供額外的功能。

CRTP

①.概述

CRTP 的基本特征表現為:基類是一個模闆類;派生類在繼承該基類時,将派生類自身作為模闆參數傳遞給基類。

②.實作示例

template<typename T>
class baseDemo
{
public:
    virtual ~baseDemo(){}
    void interface()
{
        static_cast<T*>(this)->imp();
    }
};

class derivedDemo:public baseDemo<derivedDemo>
{
public:
    void imp()
{
        cout << " hello world " << endl;
    }
};
           

靜态多态

①.概述

多态是指同一個方法在基類和不同派生類之間有不同的實作,C++ 通過虛函數實作多态,但是虛函數會影響類的記憶體布局,并且虛函數的調用會增加運作時的開銷。

②.靜态多态

CRTP 可以實作靜态多态,但本質上 CRTP 中的多個派生類并不是同一個基類,是以嚴格意義上不能叫多态。

template<typename T>
class baseDemo
{
public:
    virtual ~baseDemo(){}
    void interface() { static_cast<T*>(this)->imp(); }
    void imp() { cout << "imp hello world " << endl; }
};

class derivedDemo1:public baseDemo<derivedDemo1>
{
public:
    void imp(){ cout << "derivedDemo1 hello world " << endl; }
};

class derivedDemo2 :public baseDemo<derivedDemo2>
{
public:
    void imp() { cout << "derivedDemo2 hello world " << endl; }
};

template<typename T>
void funcDemo(T & base)
{
    base.interface();
}

int main()
{
    derivedDemo1 d1;
    derivedDemo2 d2;

    funcDemo(d1);
    funcDemo(d2);
   
    return 0;
}
           
C++ 慣用法之 CRTP

代碼複用

①.概述

使用 CRTP 可以把重複性的代碼抽象到基類中,減少代碼備援。

②.代碼示例

template<typename T>
class baseDemo
{
public:
    virtual ~baseDemo(){}
    void getType() 
{ 
        T& t = static_cast<T&>(*this);
        cout << typeid(t).name() << endl;
    }
  
};

class derivedDemo1:public baseDemo<derivedDemo1>
{
};

class derivedDemo2 :public baseDemo<derivedDemo2>
{
};

int main()
{
    derivedDemo1 d1;
    derivedDemo2 d2;

    d1.getType();
    d2.getType();
    
    return 0;
}
           
C++ 慣用法之 CRTP

擴充既有類的功能

①.概述

使用 CRTP 可以在基類中調用派生類的成員函數,進而可以在調用前後擴充新的操作。

②.代碼示例

template<typename T>
class baseDemo
{
public:
    virtual ~baseDemo() {}
    void interface()
{
        cout << "hello " << endl;
        static_cast<T*>(this)->imp();
    }
};

class derivedDemo :public baseDemo<derivedDemo>
{
public:
    void imp()
{
        cout << "derivedDemo " << endl;
    }
};

int main()
{
    derivedDemo demo;
    demo.interface();
    
    return 0;
}
           
C++ 慣用法之 CRTP

CRTP 應用示例

應用 CRTP 可以把一個類變為單例模式,代碼如下:

template<typename T>
class singlePatternTemplate
{
public:
    virtual ~singlePatternTemplate() {}
    singlePatternTemplate(const singlePatternTemplate&) = delete;
    singlePatternTemplate & operator=(const singlePatternTemplate&) = delete;

    static T& getSingleObj()
{
        static T obj;
        return obj;
    }
protected:
    singlePatternTemplate(){}
};

class derivedDemo :public singlePatternTemplate<derivedDemo>
{
    friend singlePatternTemplate<derivedDemo>;
private:
    derivedDemo(){}
};
           
C++ 慣用法之 CRTP

繼續閱讀