2015-10-21 28 views
3

時訪問基類的構造需要插入克隆和創建成員函數上我的課hieararchy我如何使用CRTP

class Base 
{ 
protected: 
    const int x_; 
public: 
    Base() : x_(0) {} 
    Base(int x) : x_(x) {} 
}; 

我認爲CRTP可能是怎樣的方式來節省一些打字和避免錯誤。

template <typename Derived> 
class CRTP_Iface : public Base 
{ 
public: 
    virtual Base *create() const { return new Derived(); } 
    virtual Base *clone() const { return new Derived(static_cast<Derived const&>(*this)); } 
}; 

不幸的是,我無法訪問基類構造函數來初始化const成員。

class D1 : public CRTP_Iface<D1> 
{ 
public: 
    D1() : Base() {} 
    D1(int x) : Base(x) {} 
}; 

class D2 : public CRTP_Iface<D2> 
{ 
public: 
    D2() : x_(0) {} 
    D2(int x) : x_(x) {} 
}; 

int main() 
{ 
    D1 a; 
    D2 b; 

    return 0; 
} 

有沒有簡單的方法來解決這個問題?

回答

3

只需將所有需要的構造函數添加到CRTP_Iface即可。

public: 
    CRTP_Iface() : Base() {} 
    CRTP_Iface(int x) : Base(x) {} 

如果使用C++ 11這個變得更簡單:

public: 
    using Base::Base; 

然後,你必須:

class D1 : public CRTP_Iface<D1> 
{ 
public: 
    D1() : CRTP_Iface() {} 
    D1(int x) : CRTP_Iface(x) {} 
}; 

...可以更好的用C++編寫11:

class D1 : public CRTP_Iface<D1> 
{ 
public: 
    using CRTP_Iface<D1>::CRTP_Iface; 
}; 

(不確定是否需要左手或::右手,AFAIR一些complilers喜歡它更爲嚴格)

1

可以繼承Base類的構造函數模板CRTP_Iface<>,然後調用它的構造函數在派生類:

template <typename Derived> 
class CRTP_Iface : public Base 
{ 
protected: 
    using Base::Base; 

public: 
    virtual Base *create() const { return new Derived(); } 
    virtual Base *clone() const { return new Derived(static_cast<Derived const&>(*this)); } 
}; 

class D1 : public CRTP_Iface<D1> 
{ 
public: 
    D1() : CRTP_Iface() {} 
    D1(int x) : CRTP_Iface(x) {} 
}; 

live example

+0

如果執行'D1 a; auto c = a.create();刪除c;' ? –

+0

@FengWang我們應該爲'Base'添加一個虛擬析構函數:http://melpon.org/wandbox/permlink/WoxkGgrhoAoAzNOt –