Придумал вот ленивую инициализацию на C++.
#include
// trace the execution (not needed in a real program)
#define TRACE(...) std::printf(__VA_ARGS__)
#include "CountedPtr.h" //
[1]
// header (.h) ---------------------------------------------------------
struct C {
virtual void foo(const char *s) const = 0;
virtual ~C() {}
static CountedPtr obj;
};
// implementation (.cc) ------------------------------------------------
struct Active : public C {
Active(const char *init_str) {
TRACE("Active(\"%s\")\n", init_str);
// heavyweight initialization procedure ...
}
~Active() {
TRACE("~Active()\n");
// freeing resources ...
}
void foo(const char *s) const {
TRACE("Active.foo(\"%s\")\n", s);
// some [believed to be] useful functionality ...
}
};
class Lazy : public C {
public:
Lazy(const char *init_str)
: _init_str(init_str) { TRACE("Lazy(\"%s\")\n", init_str); }
~Lazy() { TRACE("~Lazy()\n"); }
void foo(const char *s) const {
TRACE("Lazy.foo(\"%s\")\n", s);
C::obj = CountedPtr(new Active(this->_init_str));
return C::obj->foo(s);
}
private:
const char * const _init_str;
};
// heavyweight initialization is delayed until it is needed
CountedPtr C::obj = CountedPtr(new Lazy("init arg(s)"));
// usage ---------------------------------------------------------------
int main()
{
// bla, bla, bla ...
C::obj->foo("woo-hoo!"); // time to use
return 0;
}
Выводит:
Lazy("init arg(s)")
Lazy.foo("woo-hoo!")
Active("init arg(s)")
~Lazy()
Active.foo("woo-hoo!")
~Active()
На работе есть программки, которые кешируют базу данных. Чтобы не вставлять
в тщательно выбранных местах вызовы типа dbcache::init(), применю,
пожалуй, эту on-demand схему...
Примечание
А, между тем, в Python все просто: у каждого объекта есть аттрибут __class__ и простым присваиванием можно менять класс объекта "на лету"
[2].
Update: все уже придумано до нас - см.
Virtual proxy.
Ссылки:
- Nicolai M. Josuttis, The C++ Standard Library - A Tutorial and Reference:
cont/countptr.hpp - ASPN: Python Cookbook: Ring Buffer
- Wikipedia: Lazy initialization