最近,我读到了一些关于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变量,不管是真是假,他们该怎么做呢?是否有强制实现纯虚函数的选项,以设置从基类继承的任何变量?
发布于 2016-01-20 16:20:19
您可以将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*); }
};发布于 2016-01-20 16:23:18
您不能检查是否设置了initialized,因为它不能表示第三个状态"undefined“。
解决方案1
保护纯虚函数,使其返回初始化值,并通过非虚包装调用
class First
{
public:
void init()
{
initialized = initImplementation();
// check initialized here
}
protected:
virtual bool initImplementation() = 0;
bool initialized;
};解决方案2
将初始化更改为枚举,其状态为undefined、non-initialized、initialized、protect纯虚拟函数并通过非虚拟包装器调用它,然后检查变量是否已设置:
class First
{
public:
void init()
{
initImplementation();
// check initialized here
}
protected:
virtual void initImplementation() = 0;
enum
{
undefined,
initialized,
uninitialized
} initialized;
};解决方案3
去掉initialized,如果出了问题,就在init()中抛出一个异常。然后,调用者就会知道出了问题。顺便说一句,你也可以从构造函数中抛出。
发布于 2016-01-20 16:27:18
好吧,虽然你的问题的直接答案是不。有一些技术可以用来保证对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类的帮助,就不能再创建这个类(这一步实际上并不是必需的,但它确实会强制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类添加一些额外的东西),但在我看来,它很好地解决了需求。
https://stackoverflow.com/questions/34894570
复制相似问题