This post就是我刚刚读到的内容。
他在C ++中实现Singleton的方式让我很困惑。我有几个问题,这是他的代码:
template<typename T>
class Singleton {
public:
static T& getInstance() { //Question 1
return instance;
}
private:
static T instance;
};
class DebugLog : public Singleton<DebugLog> { //Question 2
public:
void doNothing() {}
};
问题
我认为我们应该将static T& getInstance()
的定义放在课堂体外,对吗?
他试图让class DebugLog
成为单身类,但当他继承Singleton<DebugLog>
时,DebugLog
尚不存在,对吧?如果正确,那么模板类Singleton
如何实例化一个不存在的类?
答案 0 :(得分:5)
1)不,你如何构建代码并不重要。顺便说一下,Singleton
不是一个类:它是一个模板。由于完整的模板定义无论如何都必须在任何实例化站点都可访问,因此您也可以内联定义所有内容。
2)class DebugLog : public Singleton<DebugLog>
没问题。我们不是从一个不存在的类继承;相反,我们继承自班级Singleton<DebugLog>
。模板可以在不完整的类型上实例化。 (对于这样的类型参数,您可以做什么和不能做什么规则。)
例如,template <typename T> class Foo { };
当然可以在任何类型上实例化而没有问题。更有趣的是,template <typename T> struct PointerFactory { typedef T * type; };
可以在任何类型上实例化,完整与否。在目前的情况下,CRTP中模板参数的目的仅仅是告知基类最终的派生类型,所以这完全没问题。
答案 1 :(得分:1)
C ++标准并没有提到关于类(或任何东西)的“存在”
其他)。在模板实例化时,查找名称查找
DebugLog
,并发现它是一个类(因此是一个类型)。在那时候,
它是一种不完整的类型,你可以做的事情有限
不完整的类型。如果是实例化的类模板
不做任何需要完整类型的事情(Singleton
没有问题,那就没问题了。 (注意只有班级
定义在此时被实例化;类成员函数会
在使用它们之前不得实例化。)
我可能会补充说,还有一件重要的事情遗漏了
您发布的代码:声明没有定义
Singleton::instance
。您仍然需要添加:
template<typename T> T Singleton<T>::instance;
的某个地方。
答案 2 :(得分:-3)
在这种情况下,您必须使用指向T的指针:
template<typename T>
class Singleton {
public:
static T& getInstance() {
static T * instance = NULL;
if (!instance)
instance = new T;
return *instance;
}
};
class DebugLog : public Singleton<DebugLog> { //Question 2
public:
void doNothing() {}
};