单例通常会以私有可见性声明其构造函数,并提供可以访问私有构造函数的工厂函数。
class singleton
{
public:
/// @brief Public factory function.
static singleton& instance()
{
static singleton instance_;
return instance_;
}
private:
// Private constructors and destructor.
singleton() {}
~singleton() {};
singleton(const singleton&);
singleton& operator=(const singleton&);
};
默认情况下,Boost.Python 假定公开可用的构造函数与提供给boost::python::class_ 构造函数的init-expression 匹配。为了抑制这种行为,可以将特殊的 boost::python::no_init 对象提供给 class_ 构造函数。此外,由于私有析构函数,class_ 需要通过提供 boost::noncopyable 作为模板参数来公开为不可复制。
BOOST_PYTHON_MODULE(example)
{
namespace python = boost::python;
python::class_<singleton, boost::noncopyable>("Singleton", python::no_init);
}
在 Python 中,单例很少通过其 API 将自己呈现为单例。因此,许多 Python 开发人员可能自然希望能够通过 example.Singleton() 实例化 Python 类,而不是使用因子方法。虽然默认构造函数已通过python::no_init 公开,但可以为__init__ 定义自定义构造函数。为了正确解释 C++ 单例,通过 Boost.Python 公开的单例将使用 boost::shared_ptr 和一个无操作删除器来保存单例的句柄。这是一个完整的例子:
#include <boost/python.hpp>
/// @brief Mock up singleton class.
class singleton
{
public:
/// @brief Public factory function.
static singleton& instance()
{
static singleton instance_;
return instance_;
}
void set_x(unsigned int x) { x_ = x; }
unsigned int get_x() { return x_; }
private:
// Private constructors and destructor.
singleton() : x_(0) {}
~singleton() {};
singleton(const singleton&);
singleton& operator=(const singleton&);
private:
unsigned int x_;
};
/// @brief No operation deleter.
void noop_deleter(void*) {};
/// @brief Helper function used to get a shared_ptr that holds
/// a singleton.
boost::shared_ptr<singleton> py_get_singleton()
{
return boost::shared_ptr<singleton>(
&singleton::instance(), // the instance
&noop_deleter); // no-op deleter
}
BOOST_PYTHON_MODULE(example)
{
namespace python = boost::python;
// Expose the singleton class, supressing the default constructor
// via python::no_init, and providing a constructor that will return
// a handle to the singleton.
python::class_<singleton, boost::shared_ptr<singleton>,
boost::noncopyable>("Singleton", python::no_init)
.def("__init__", python::make_constructor(&py_get_singleton))
.add_property("x", &singleton::get_x, &singleton::set_x)
;
}
及其用法:
>>> import example
>>> s1 = example.Singleton()
>>> s2 = example.Singleton()
>>> s1.x
0
>>> s2.x
0
>>> s1.x = 5
>>> s2.x
5
请注意,从 Python 的角度来看,这更类似于 borg 或单态模式,因为它们共享状态,而不是身份。 (即s1.x == s2.x,但id(s1) != id(s2)。)如果Python 类也需要是单例,而不仅仅是它的状态,那么可能需要使用Python 代码而不是C++ 来实现此行为。