【发布时间】:2012-07-08 08:38:33
【问题描述】:
我有一个抽象的单例类。我的目标是任何子类只需要实现 init() 函数就可以了。这是我所做的:
template <typename T>
class Singleton
{
public:
Singleton()
{
init();
}
static T& instance()
{
static T instance;
return instance;
}
protected:
virtual void init() = 0;
};
class SubSingleton : public Singleton<SubSingleton>
{
protected:
void init()
{
cout << "Init SubSingleton" << endl;
}
};
这不会编译,因为 init() 是受保护的,不能从公共静态函数中调用。这个问题有2个解决方案。首先我们可以公开 init() 函数,但我不想公开这个函数。所以这只剩下第二种解决方案,改变子类如下:
class SubSingleton : public Singleton<SubSingleton>
{
friend class Singleton<SubSingleton>;
protected:
void init()
{
cout << "Init SubSingleton" << endl;
}
};
这很好用,但我不想要朋友声明,因为其他程序员可能会扩展我的代码并且可能不知道应该添加它。
如果没有朋友声明,还有其他方法可以实现吗?也许是 Andrei Alexandrescu 的作品?
编辑:现在在构造函数中调用 init 函数而不是 instance() 函数。
EDIT2:出于技术原因和兼容性,我需要一个 init() 函数,不能只在构造函数中进行初始化。
强制转换的解决方案有效,但如果我从构造函数调用 init(),则强制转换不再有效。有什么建议吗?
【问题讨论】:
-
调用
instance()两次会导致init()被调用两次:这正常吗? -
template<class> Singleton;是什么意思?似乎并不要求派生类实际上是单例,所以让派生类像往常一样在其构造函数中执行初始化不是更简单吗? (事实上,即使你想要求派生类是单例的,我仍然看不到总是在构造函数之后立即调用的“init”函数的原因。) -
首先:您现在不创建实例,其次:bool isInit 会有所帮助,但您在这里所期望的可能是 Create 而不是 Init。目前似乎有点混乱。
-
在你的“edit2”之后:你不应该从基构造函数调用 init(),因为当基构造函数被调用时,派生对象(即它的成员)还不存在。因此,即使您静态调用 derived::init(),您也无法做任何有用的事情。
标签: c++ templates inheritance singleton friend