2011-11-21 21 views
0

This post就是我刚才读的。如何在C++中实现Singleton

他在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() {} 
}; 

问题

  1. 我想我们应该把static T& getInstance()的定义类主体以外的,对不对?

  2. 他试图让class DebugLog成为一个单独的类,但是当他继承Singleton<DebugLog>时,DebugLog不存在了吧?如果对,那么模板类Singleton如何实例化一个不存在的类?

+4

1 - 你不需要。 2 - [好奇地重复出现的模板模式](http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern)。 – birryree

+0

@birryree,谢谢。 – Alcott

回答

1
  1. 这肯定会是更清洁,如果函数是的 定义在类外,使代码更容易阅读和维护。然而,在这个 的情况下,完整的课程足够小,以至于 的差别不是很大,当然,因为我们正在处理模板,所以在每个翻译单元中仍然必须包含实际定义 它使用它。

C++标准不存在“的”与问候类(或任何其他 )说。在模板实例化处,名称查找找到 DebugLog,并发现它是一个类(因此是一个类型)。在那一点上, 它是一个不完整的类型,只有有限的东西,你可以做一个不完整的类型 。如果实例化的类模板 没有做任何需要完整类型的事情(并且Singleton 没有),那么没有问题。 (请注意,此时只有类 定义被实例化;类成员函数 在使用前不会被实例化。)

我可能会补充说,您发布的 代码中仍缺少一件重要的东西:声明 Singleton::instance没有定义。您仍然需要添加:

template<typename T> T Singleton<T>::instance; 

某处。

+0

是的,这是缺少的。此外,为了使Singleton成为一个真正的Singleton,我认为我们应该让Singleton的Singleton ()成为一个protected/private成员函数,对吧? – Alcott

+0

@Alcott由于'Singleton '被设计为派生自,因此使其构造器受到保护似乎是一个好的举措。有一件事'Singleton '不能做,那需要做的是确保'DebugLog'具有一个私有构造函数,并且'Singleton '是朋友,为了使用它。 –

+0

没错,:)。另一件事是,成员函数何时会在模板类中实例化? – Alcott

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中模板参数的目的仅仅是为了通知基类它的最终派生类型,所以这是完全正确的。

+0

这是否意味着,当一个类继承模板类时,模板参数是什么并不重要,对吧? – Alcott

+0

@Alcott:这与继承没有任何关系。唯一的问题是你是否可以实例化模板。 –

-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() {} 
}; 
+0

你为什么“必须”使用指针? – duedl0r

+0

-1您不仅“不得”使用静态指针实例,还不会破坏代码中的对象。 – Artyom