2016-01-20 110 views
1

最近我讀在C++中一些關於純虛函數的概念,我不知道,因爲下面的代碼:純虛函數

class First 
{ 
public: 
    virtual void init() = 0; 
protected: 
    bool initialized; 
}; 

class Second : public First 
{ 
public: 
    void init() { ((*someting*) ? (initialized=true) : (initialized=false)); 
}; 

如果First類的創作者想要確保init() MUST的執行設置initialized變量是真是假他們怎麼能這樣做?是否有強制執行純虛函數來設置從基類繼承的任何變量的選項?

+0

_「是否有強制執行純虛函數來設置從基類繼承的任何變量的選項?」_編號 –

+0

您可以做的是在聲明它時將bool成員設置爲false(或true) (在基類中) – sop

+0

可惜...無論如何,@πάνταῥεῖ - 感謝您的快速回答! – michelson

回答

3

您可以讓init受保護並返回bool。 然後有一個新的initialize方法是公開的,也設置initialized成員。

由於init現在有一個返回值,它必須由實現派生類的任何人設置。

class First 
{ 
public: 
    void initialize() { initialized = init(); } 

protected: 
    virtual bool init() = 0; 
    bool initialized; 
}; 

class Second : public First 
{ 
public: 
    bool init() { return (*something*); } 
}; 
1

你不能檢查,如果initialized已設置與否,因爲它不能代表第三狀態「不確定」。

溶液1

保護純虛函數,使其返回初始值,並經由非虛擬包裝

class First 
{ 
public: 
    void init() 
    { 
     initialized = initImplementation(); 
     // check initialized here 
    } 
protected: 
    virtual bool initImplementation() = 0; 
    bool initialized; 
}; 

溶液2

變化初始化調用它枚舉狀態爲未定義,未初始化,初始化,保護純虛函數並通過非虛包裝調用它,t然後帽子檢查,如果變量已設置:

class First 
{ 
public: 
    void init() 
    { 
     initImplementation(); 
     // check initialized here 
    } 
protected: 
    virtual void initImplementation() = 0; 
    enum 
    { 
     undefined, 
     initialized, 
     uninitialized 
    } initialized; 
}; 

解決方案3

擺脫初始化,只是拋出一個異常,在init(),如果出現錯誤。來電者會知道發生了問題。作爲一個旁註,你也可以從構造函數中拋出。

0

那麼,而你的問題的直接回答是沒有。您可以使用一些技巧來獲得您的init功能的保證電話。 比方說,你有下面的基類:

class Base 
{ 
public: 
    virtual void init() = 0; 
private: 
    bool initialized = false; 
}; 

void Base::init() 
{ 
    std::cout << "Called from base!\n"; 
    initialized = true; 
} 

及以下得出:

class Derived: public Base 
{ 
    friend class Enforcer<Derived>; 
public: 
    void init() override 
    { 
     std::cout << "Called from derived!\n"; 
    } 
private: 
    Derived() 
    { 
    } 
private: 
    using BaseClass = Base; 
}; 

看私人構造函數和友元聲明:您可以在不的幫助沒有更多的創建這個類Enforcer class(這一步並非真正需要,但它會真正強制Derived類的任何用戶使用Enforcer)。現在,我們需要寫Enforcer類,那就是:

template<typename T> 
class Enforcer: public T 
{ 
public: 
    template<typename... Args> 
    Enforcer(Args&&... arg): T(std::forward<Args>(arg)...) 
    { 

    } 

    void init() override 
    { 
     T::init(); 
     T::BaseClass::init(); 
    } 
}; 

ideone整個例子。

是的,它有它的缺點(你需要添加一些額外的東西到Derived類),但它在我看來非常整齊地解決了這個需求。