纯虚函数必须设置变量

时间:2016-01-20 08:03:53

标签: c++ inheritance pure-virtual

最近我在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()的实现必须设置initialized变量的真或假,他们怎么能这样做?是否有一个选项来强制执行纯虚函数来设置从基类继承的任何变量?

3 个答案:

答案 0 :(得分:3)

您可以对private void timer1_Tick(object sender, EventArgs e) { JobSQL.Refresh(); if (JobSQL.CurrentRunStatus == JobExecutionStatus.Executing) { List<JobSchedule> listSchedule = new List<JobSchedule>(); foreach (JobSchedule JobSchedule in JobSQL.JobSchedules) { if (JobSchedule.IsEnabled == true) { listSchedule.Add(JobSchedule); } } foreach (JobSchedule item in listSchedule) { MessageBox.Show("Schedule run is -----" + item.Name.ToString()); } } } 进行保护并让其返回init。 然后使用新的bool方法,该方法是公开的,并设置initialize成员。

由于initialized现在有一个返回值,所以必须由实现派生类的任何人设置。

init

答案 1 :(得分:1)

您无法检查是否已设置initialized,因为它不能代表第三个状态“未定义”。

解决方案1 ​​

保护纯虚函数,使其返回初始化值并通过非虚拟包装器调用

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

解决方案2

将初始化更改为枚举状态未定义,未初始化,初始化,保护纯虚函数并通过非虚拟包装调用,然后检查变量是否已设置:

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

解决方案3

摆脱初始化,如果出现问题,只需在init()中抛出异常。然后呼叫者会知道出了问题。 作为旁注,您也可以从构造函数中抛出。

答案 2 :(得分: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类的帮助,你就不能再创建这个类了(这一步并不是真的需要,但它会真正强迫{{1}的任何用户} class使用Derived)。现在我们需要编写Enforcer类,这里是:

Enforcer

ideone上的整个示例。

是的它有它的缺点(你需要在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(); } }; 类中添加一些额外的东西)但是在我看来它非常巧妙地解决了这个要求。