2017-02-20 54 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。 –

相關問題