我目前正在尝试用 C++ 实现一些我一直用 Java 做的事情:假设我有一个函数 bool init()
作为我类的一员A
在 A
的构造函数中被调用如果它返回 false
,构造函数将抛出异常。
现在我创建一个新类 B
源自 A
但它需要执行不同的初始化,所以它会返回 true
在与原始情况不同的情况下 A::init()
.
在 Java 中,我会简单地继续并覆盖 B
中的方法。当 A
的构造函数时参与构建过程B
, 它会调用 B::init()
来自 A 的构造函数,它运行得非常出色。
但是在 C++ 中,我刚刚了解到我不能在构造函数中调用虚函数(我可以,但它的行为方式不同)。我现在的问题是,我如何处理从构造函数调用但可能需要在类的派生类中更改的此类初始化/检查。
一种方法当然是不在构造函数中调用它,而是让程序员显式调用 init()
。创建对象后运行,但我不喜欢这样,因为这可能会被遗忘,导致奇怪的对象状态。
小例子:
考虑一下 A
和 B
读取硬编码文件的内容。 A
阅读 fileA.txt
和 B
阅读 fileB.txt
.我希望对象的构造只有在相应的文件存在时才会成功。因此,检查必须在对象的构造函数中进行。如果直接将检查写入构造函数将导致 B
总是失败(假设两个文件不能同时存在)所以我总是去定义一个函数来执行检查并且可以被覆盖。执行此操作的 C++ 方法是什么?
最佳答案
虽然让派生类调用它自己的 init 函数似乎更合适,
作为替代方案,您可以创建调用 virtual
init
方法的工厂函数:
class A
{
public:
virtual ~A() = default;
virtual bool init() = 0;
public:
template <typename T, typename ... Ts>
static T Create(Ts&&...args)
{
static_assert(std::is_base_of<A, T>::value);
T derived(std::forward<Ts>(args)...);
if (!derived.init()) {
throw std::runtime_error("...");
}
return derived;
}
protected:
A() = default;
};
class B : public A
{
friend class A; // For factory
protected:
B(/*..*/);
public:
bool init() override;
};
关于C++ 在构造函数中初始化对象(多态),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58034851/