goo*_*ons 5 c++ inheritance singleton templates friend
我有一个抽象的单例类。我的目标是任何子类只需要实现 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;
}
};
Run Code Online (Sandbox Code Playgroud)
这不会编译,因为 init() 受到保护并且不能从公共静态函数调用。这个问题有两种解决方案。首先我们可以将 init() 函数公开,但我不想公开这个函数。所以这就只剩下第二种解决方案了,将子类改成如下:
class SubSingleton : public Singleton<SubSingleton>
{
friend class Singleton<SubSingleton>;
protected:
void init()
{
cout << "Init SubSingleton" << endl;
}
};
Run Code Online (Sandbox Code Playgroud)
这工作得很好,但我不想要朋友声明,因为其他程序员可能会扩展我的代码并且可能不知道应该添加它。
有没有其他方法可以在没有朋友声明的情况下实现这一点?也许安德烈·亚历山德雷斯库有什么东西?
编辑:现在在构造函数中调用 init 函数而不是 instance() 函数。
EDIT2:出于技术原因和兼容性,我需要一个 init() 函数,并且不能只在构造函数中进行初始化。
强制转换的解决方案有效,但如果我从构造函数调用 init() ,则强制转换将不再起作用。有什么建议么?
问题是您没有按照预期使用虚拟函数。即,现在没有多态性在起作用。为什么?因为您在直接派生对象上调用 init() 。当您在基类引用或基类指针上调用 init() 时,就会使用虚拟的 init() 函数,如下所示。然后调用发生在基类作用域中,并且由于instance()方法是基类方法,因此从该方法调用受保护的方法是完全可以的。
static T& instance()
{
static T myInstance;
Singleton<T>& t = myInstance; // Just define a dummy reference here.
t.init();
return myInstance;
}
Run Code Online (Sandbox Code Playgroud)