称之为;初始化";调用对象的一个成员函数时对象中的函数 我试图在C++中实现惰性初始化,我正在寻找一种很好的方法来调用初始化()//>代码>成员函数,当一些其他的方法,如代码>对象-> GETNAMEL()//CUL>被调用时,
目前,我已按如下方式实施:称之为;初始化";调用对象的一个成员函数时对象中的函数 我试图在C++中实现惰性初始化,我正在寻找一种很好的方法来调用初始化()//>代码>成员函数,当一些其他的方法,如代码>对象-> GETNAMEL()//CUL>被调用时,,c++,c++11,C++,C++11,目前,我已按如下方式实施: 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()
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;
}
};
struct ReadFromDatabase
{
void operator()(std::string& target) const
{
std::cout << "initializing...\n";
target = "hello!";
}
};
struct Foo
{
lazily_initialized<std::string, ReadFromDatabase> _str;
};
这正是我目前所需要的。但是为每个方法设置初始化检查是非常繁琐的,所以我想去掉它。如果有人知道C++中的一个好方法来改进上面的例子,我想知道!p>
例如,当使用->
时,是否可以使用操作符
来实现调用Initialize()
谢谢 可能在构造函数中调用它 编辑:嗯,我没抓住你问题的重点。对不起。 那么延迟工厂初始化呢?
可能在构造函数中调用它 编辑:嗯,我没抓住你问题的重点。对不起。 那么延迟工厂初始化呢?
听起来像是模板的工作!创建一个采用类型
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;
}
};
如注释中所述,为了表示“未初始化状态”,应使用
std::optional
或boost::optional
而不是单独的bool
字段。这允许将非默认可构造类型与延迟初始化的一起使用,也使代码更加优雅和安全
因为前者需要C++17,而后者需要boost
,所以我使用了一个单独的bool
字段来尽可能地简化我的答案。一个真正的实现应该考虑使用<代码>可选< /> >,使用<代码> No.< /COD>适当的地方,并考虑暴露<<代码> const >合格>代码> GET()/<代码>,返回一个<代码> const t/< /c> > 听起来像模板的一个工作!创建一个采用类型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;
}
};
如注释中所述,为了表示“未初始化状态”,应使用std::optional
或boost::optional
而不是单独的bool
字段。这允许将非默认可构造类型与延迟初始化的一起使用,也使代码更加优雅和安全
因为前者需要C++17,而后者需要boost
,所以我使用了一个单独的bool
字段来尽可能地简化我的答案。一个真正的实现应该考虑使用<代码>可选的<代码>,使用<代码> NO>除<代码>之外,也考虑暴露一个<代码> const >合格>代码> GET()/<代码>,返回一个<代码> const t/< /c>。< /p>在构造函数中初始化对象。@使用延迟加载,因此只有在实际尝试访问对象时才会填充对象数据。这就是为什么要使用initialized
机制。让if(!initialized)
检查Initialize
功能如何?然后,GetName
函数所要做的就是调用Initialize()
。您可以使用惰性工厂。如果之前没有使用给定参数实例化对象,则只会创建该对象。虽然这并不完全是您想要的。如果您通过指针访问这些对象,您可以创建自己的智能指针,该指针将在操作符->中调用Initialize()
和get()
方法。但这取决于您实际想要如何使用它。在构造函数中初始化您的对象。@RichardCritten这违背了延迟加载的目的。使用延迟加载,因此只有在实际尝试访问对象时才会填充对象数据。这就是为什么要使用initialized
机制。让if(!initialized)
检查Initialize
功能如何?然后,GetName
函数所要做的就是调用Initialize()
。您可以使用惰性工厂。如果之前没有使用给定参数实例化对象,则只会创建该对象。虽然这并不完全是您想要的。如果您通过指针访问这些对象,您可以创建自己的智能指针,该指针将在操作符->中调用Initialize()
和get()
方法。但这取决于您实际想要如何使用它。@Aenons请参阅我上面的评论。这违背了延迟加载的全部目的,因此这不是实现它的方法。@Aenons请参阅我上面的评论。这违背了延迟加载的全部目的,因此这不是实现它的方法。可能是TInitializer::operator()
代替static\u cast(*这个)对于没有默认构造函数的类型,
可选的
可能比T
+bool
更好。@Jarod42:我考虑过,但问题被标记为C++11。我没有添加名称空间前缀,以便根据需要提高的使用率;-)可能是TInitializer::operator()
代替static\u cast(*这个)对于没有默认构造函数的类型,
可选的
可能比T
+bool
更好。@Jarod42:我考虑过,但问题被标记为C++11。我没有添加名称空间前缀,以便根据需要提高的使用率;-)