2012-11-19 97 views
0

在我的項目之一,我用同樣的方法CRTP(從enable_crtp派生)在回答1瀏覽:How do I pass template parameters to a CRTP?如何處理CRTP的類層次?

不過,我有必要從派生類派生了。有沒有什麼辦法讓與了落回到剛纔的static_cast this指針,但是通過使用來自啓用CRTP基類的自()方法,這項工作?

#include "EnableCRTP.h" 

template<typename DERIVED> 
class BASE : public EnableCRTP<DERIVED> 
{ 
    friend DERIVED; 
public: 
    void startChain() 
    { 
     self()->chain(); 
    } 
}; 

template<typename DERIVED> 
class Derived1 : public BASE<Derived1<DERIVED> > 
{ 
public: 
    void chain() 
    { 
     std::cout << "Derived1" << std::endl; 

     //self()->chain2(); <- compile Error 
     static_cast<DERIVED*>(this)->chain2(); // <-Works 
    } 
}; 

class Derived2 : public Derived1<Derived2> 
{ 
public: 
    void chain2() 
    { 
     std::cout << "Derived2" << std::endl; 
    } 
}; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    Derived2 der;  
    der.startChain();  
    return 0; 
} 

回答

1

您可以將派生最多的類作爲模板參數提供給CRTP基類,以便它可以訪問其所有成員。取而代之的

template<typename DERIVED> 
class Derived1 : public BASE<Derived1<DERIVED> > 

用途:

template<typename DERIVED> 
class Derived1 : public BASE<DERIVED> 

也有你的代碼的其他問題。例如,你不能直接調用self()像你這樣,因爲編譯器不知道self是基類(這是依賴於模板參數)的成員。相反,調用this->self()。見this FAQ entry

0

做你想做什麼,你只能通過CRTP傳遞最派生類。在這種情況下,你需要Derived1的定義更改爲以下:

template<typename DERIVED> 
class Derived1 : public BASE<DERIVED> 
{ 
public: 
    void chain() 
    { 
     std::cout << "Derived1" << std::endl; 

     this->self()->chain2(); // should work now 
     //static_cast<DERIVED*>(this)->chain2(); // <-Works 
    } 
}; 

此外,使用CRTP與類層次結構時,它通常是更好地建立層次結構,使得類要麼設計成可導出從(並因此是被傳遞派生類的模板),或是所述分層結構的葉,而不是衍生自。這些葉類不一定是模板。