2016-04-15 53 views
4

我有這樣的類層次結構:我可以將CRTP與多個派生類一起使用,並以多態方式使用它們嗎?

template <class Type> 
class CrtpBase 
{ 
protected: 
    Type& real_this() 
    { 
     return static_cast<Type&>(*this); 
    } 
}; 

template <class ChildType> 
class Base : CrtpBase<ChildType> 
{ 
public: 
    void foo() 
    { 
     this->real_this().boo(); 
    } 
}; 

class Derived1 : public Base<Derived1> 
{ 
public: 
    void boo { ... } 
}; 

class Derived2 : public Base<Derived2> 
{ 
public: 
    void boo { ... } 
}; 

的事情是,我想用我的課以這樣的方式

std::vector<Base*> base_vec; 
base_vec.push_bach(new Derived1()); 
base_vec.push_bach(new Derived2()); 
......... 
base_vec[0]->foo(); 

但是,這是不可能的,因爲所有派生基類類是不同的(實際上Base不是一個類型,它是模板)。那麼,有沒有辦法使用crtp與多個派生類,以及多態?

回答

3

確實有,你需要添加相應的非模板基類也:

class AbstractBase 
{ 
public: 
    virtual ~AbstractBase() {} 

    virtual void foo() = 0; 
}; 


template <class ChildType> 
class Base : CrtpBase<ChildType>, public AbstactBase 
{ 
    void foo() override { this->real_this().boo(); } 
}; 

然後,聲明你的向量作爲std::vector<AbstractBase*>

這確實會引入動態分派的開銷(您可能試圖通過使用CRTP來避免這種開銷),但動態分派是獲得C++運行時多態性的唯一方法。

儘管如此,它仍然是有益的。例如,如果所有派生類共享foo的實現,但調用許多不同的boo樣式函數(每個派生類具有不同的實現方式),則僅在調用foo時支付一次動態調度成本,然後內的所有呼叫都在foo內靜態調度,CRTP風格。

在另一方面,如果它的內foo只需一個電話到boo樣的功能,你不妨做boo虛擬的,把非虛foo到基礎,從而擺脫CRTP的。成本將是相同的:非虛擬調度(foo)和虛擬調度(boo)。


側面說明,你應該認真考慮在std::vector存儲智能指針; 擁有原始指針是不好的做法。

+0

我用過crtp的所有東西都是爲了避免虛函數,那麼這個解決方案的含義是什麼?引入crtp類來避免虛函數,然後使用具有虛函數的抽象類來解決這個問題?廢話 – user1289

+1

@ user1289那麼,CRTP是一個編譯時解決方案,這意味着你有基於不同類型的編譯時調度。然後你要求具有相同的類型,這意味着運行時調度和虛擬功能。請注意,'boo()'仍然是靜態調度的。 – Angew

+0

@Angew,沒有crtp也只會需要一個運行時調度,在這種情況下,我有一個運行時和一個靜態,可能比沒有使用crtp更差。我的問題可能沒有解決辦法,只是想檢查一下是否存在黑客攻擊。 – user1289

相關問題