称之为;初始化";调用对象的一个成员函数时对象中的函数 我试图在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。我没有添加名称空间前缀,以便根据需要提高
的使用率;-)