调用对象中的"initialize"函数时调用其成员函数之一

Call an "initialize" function in an object when one of its member functions are called

本文关键字:调用 函数 成员 initialize 对象      更新时间:2023-10-16

我正在尝试在C++中实现延迟初始化,并且我正在寻找一种在调用其他方法(如object->GetName())时调用Initialize()成员函数的好方法。

现在我已经实现了如下:

class Person
{
protected:
bool initialized = false;
std::string name;
void Initialize()
{
name = "My name!"; // do heavy reading from database
initialized = true;
}
public:
std::string GetName()
{
if (!initialized) {
Initialize();
}
return name;
}
};

这正是我目前所需要的。但是为每个方法设置初始化检查非常繁琐,所以我想摆脱它。如果有人知道C++改进上述示例的好方法,我想知道!

例如,当使用->时,也许operators可以用来实现呼叫Initialize()

谢谢!

听起来像是模板的工作!创建一个lazily_initialized包装器,该包装器采用类型T函数对象TInitializer类型:

template <typename T, typename TInitializer>
class lazily_initialized : TInitializer
{//                      ^^^^^^^^^^^^^^
// inheritance used for empty-base optimization
private:
T _data;
bool _initialized = false;
public:
lazily_initialized(TInitializer init = {}) 
: TInitializer(std::move(init))
{
}
T& get()
{
if(!_initialized)
{
static_cast<TInitializer&>(*this)(_data);
_initialized = true;
}
return _data;
}
};

您可以按如下方式使用它:

struct ReadFromDatabase
{
void operator()(std::string& target) const
{
std::cout << "initializing...n";
target = "hello!";
}
};
struct Foo
{
lazily_initialized<std::string, ReadFromDatabase> _str;  
};

例:

int main()
{
Foo foo;
foo._str.get(); // prints "initializing...", returns "hello!"
foo._str.get(); // returns "hello!"
}

魔杖盒示例


正如Jarod42在评论中提到的,应该使用std::optional<T>boost::optional<T>而不是单独的bool字段来表示"未初始化的状态"。这允许非默认可构造类型与lazily_initialized一起使用,并且还使代码更加优雅和安全。

由于前者需要C++17,后者需要boost,我使用了一个单独的bool字段来使我的答案尽可能简单。真正的实现应该考虑使用optional,在适当的情况下使用noexcept,并考虑公开返回const T&const限定get()

也许在构造函数中调用它?

编辑:呃,对不起,我错过了你问题的重点。 惰性工厂初始化呢? https://en.wikipedia.org/wiki/Lazy_initialization#C.2B.2B