2016-01-20 113 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类),但它在我看来非常整齐地解决了这个需求。