gpt4 book ai didi

c++ - 如何避免两步初始化

转载 作者:行者123 更新时间:2023-11-30 03:35:05 25 4
gpt4 key购买 nike

我想在我的代码中遵循 RAII(资源获取即初始化)习惯用法,但我也在做模板方法模式,我正在开发我的类的通用版本并使用它们为确定的事情。有时我需要强制执行一个初始化序列,我需要在构造函数中调用专用对象的虚函数,但这在 C++ 中是不可能的。我能想到的唯一解决方案是在创建对象后通过调用 init 函数进行两步初始化,但这打破了 RAII 习惯用法。有什么解决办法吗?

#include <memory>

class A
{
public:
A()
{
// I want to call B's foo() here
}
virtual void foo() = 0;
};

class B : public A
{
public:
B() {}
virtual void foo() {}
};

int main()
{
std::unique_ptr<A> a(static_cast<A*>(new B));

// Use b polymorphically from here...
}

编辑:似乎我的示例过于简单,这是另一个可能更好地说明我正在尝试做的事情的示例:

#include <memory>
#include <iostream>

class A
{
public:
A()
{
foo();
}
void init()
{
// bar() must be executed every time A is created but the derived classes will decide how to implement it
bar();
};
void foo() { std::cout << "Part 1 of algo\n"; };
virtual void bar() = 0;
};

class B : public A
{
public:
B() {}
virtual void bar() { std::cout << "Part 2 of algo\n"; }
};

int main()
{
std::unique_ptr<A> a(static_cast<A*>(new B));
a->init(); // I don't want to have to call this every time I instanciate it
}

最佳答案

不要为此使用虚拟调度。

A(std::function<void(A*)> foo)
{
foo(this);
}

A(std::function<void()> foo)
{
foo();
}

现在 A 的子类型将 foo 的主体传递给 A 构造函数。当然,这个 foo 最好不要依赖于有效的 B 甚至 A

您可以将构造限制为私有(private)/ protected 路径,并在其最终的伪构造函数中要求分阶段初始化。也许有一个 CRTP 助手,后代应该使用它来实现分阶段(DRY)。

但是这个要求是一个危险信号,表明您的类型可能充满了意大利面条式逻辑。有时是必需的,但通常是可以避免的。

另一种完全不同的方法是丢弃特定的 C++ 内置 OO 系统,如果它不符合您的需求。有无数种方法可以实现 OO;假设内置的 C++ 方法最适合您的问题是锤钉解决方案(您有一把锤子,所以问题看起来像钉子)。

例如,如果您规范化类型并将继承作为实现细节,或者编写您自己的 vtable,两阶段初始化的“问题”就会消失(因为这些将初始化包装在另一层抽象中)。

学习 Smalltalk、Perl、C、Python、C#/COM/.net、MFC、Objective-C、Haskell、Javascript 和 Lua 中惯用的 OO“工作”方式(作为我头脑中的一组示例) 都应该为您提供不同的方法来处理“手动”面向对象的解决方案(有一些重叠)。

关于c++ - 如何避免两步初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41517293/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com