最近我在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
变量的真或假,他们怎么能这样做?是否有一个选项来强制执行纯虚函数来设置从基类继承的任何变量?
答案 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();
}
};
类中添加一些额外的东西)但是在我看来它非常巧妙地解决了这个要求。