2017-02-20 57 views
1

我想实现懒惰初始化在C++中,我正在寻找一种很好的方式来调用Initialize()成员函数,当其他方法如object->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; 
    } 
}; 

这不正是我需要暂时。但是为每种方法设置初始化检查都非常繁琐,所以我想摆脱这一点。如果有人知道用C++改进上述示例的一种好方法,我想知道!

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

谢谢!

+0

在构造函数中初始化您的对象。 –

+0

@RichardCritten这打破了懒加载的目的。使用延迟加载,因此只有在实际访问对象时才会填充对象数据。这就是你使用'initialized'机制的原因。 –

+4

如何在'Initialize'函数中检查'if(!initialized)'?然后,所有'GetName'函数都要调用'Initialize()'。 –

回答

2

听起来像模板的工作!创建一个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!" 
} 

example on wandbox


作为评价提到Jarod42std::optional<T>boost::optional<T>应使用单独的bool字段,以表示“未初始化状态”。这允许非默认构造的类型与lazily_initialized一起使用,并且还使代码更优雅和更安全。

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

+0

也许'TInitializer ::运算符()'到位的static_cast 的'(*此)'' – Caleth

+0

可选'可能比'T' +'bool'没有默认构造函数,更好地为类型。 – Jarod42

+0

@ Jarod42:我认为,但问题被标记为C++ 11。 –

相关问题