What is the proper way to implement a getter method for a lazily-initialized member variable and maintain const-correctness? That is, I would like to have my getter method be const, because after the first time it is used, it's a normal getter method. It is only the first time (when the object is first initialized) that const does not apply. What I would like to do:
class MyClass { MyClass() : expensive_object_(NULL) {} QObject* GetExpensiveObject() const { if (!expensive_object_) { expensive_object = CreateExpensiveObject(); } return expensive_object_; } private: QObject *expensive_object_; };
Can I eat my cake and have it too?
I propose encapsulating James Curran's answer into a class of its own if you do this frequently:
template <typename T> class suspension{ std::tr1::function<T()> initializer; mutable T value; mutable bool initialized; public: suspension(std::tr1::function<T()> init): initializer(init),initialized(false){} operator T const &() const{ return get(); } T const & get() const{ if (!initialized){ value=initializer(); initialized=true; } return value; } };
Now use this in your code as follows:
class MyClass { MyClass() : expensive_object_(CreateExpensiveObject) {} QObject* GetExpensiveObject() const { return expensive_object_.get(); } private: suspension<QObject *> expensive_object_; };
That's fine and is the typical way of doing it.
You will have to declare expensive_object_
as mutable
mutable QObject *expensive_object_;
mutable
basically means "I know I'm in a const object, but modifying this won't break const-ness."
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With