Singleton design pattern

Key Points On Learning:

    1)    Protected constructor
    2)    Protected copy constructor and assignment operator
    3)    POD types

  // Declaration
  class
Singleton
  {
      public:
          static Singleton* Instance();
      protected:
          Singleton();                                // constructor
          Singleton(const Singleton&);                // copy constructor
          Singleton& operator= (const Singleton&);    // assignment operator
      private:
          static Singleton* pinstance;
  };

  // Definition
  Singleton* Singleton::pinstance = 0;    // initialize pointer
  Singleton* Singleton::Instance ()
  {
      if (pinstance == 0) // is it the first call?
      { 
          pinstance = new Singleton; // create sole instance
      }
      return pinstance; // address of sole instance
  }
  Singleton::Singleton()
  {
      //... perform necessary instance initializations
  }

建構子是 protected, 因此無法使用直接宣告或動態配置的方式來建立物件:
   
    Singleton* obj1 = new Singleton();
    Singleton obj2;

可以確保只存在一份實體的物件,以下的程式碼回傳的皆是同一個實體

  Singleton *p1 = Singleton::Instance();
  Singleton *p2 = p1->Instance();
  Singleton & ref = * Singleton::Instance();


Appendix 1. Use private copy constructor and assignment operator to avoid object copying

If you don't want users of your class to be able to assign objects of its type (password string objects are a good example), you can declare a private assignment operator and copy constructor. Please note that the compiler-synthesized copy constructor and assignment operator are public, therefore, you have to define them explicitly as private members in this case. For example:

class NoCopy {
    private:
        NoCopy& operator = (const NoCopy& other) {/*..*/}
        NoCopy(const NoCopy& other) {/*..*/}
    public:
        //...
};

void f()
{
    NoCopy nc;         //fine, default constructor called
    NoCopy nc2(nc);    //compile time error; attempt to call a private copy constructor
    nc2 = nc;          //also a compile time error; operator= is private
}


Appendix 2. What is difference between [Singleton* obj = new Singleton;] and [Singleton* obj = new Singleton();]

首先必須先了解何謂 POD type,在C++的標準中有定義,而以下有一段來自於MSDN Magazine的說明:

C++ Q&A Calling Virtual Functions, Persisting View State, POD Type -- MSDN Magazine, November 2004

Q I've seen the term "POD type" occasionally in literature and documentation about C++ and the Microsoft® .NET Framework. What is a POD type?
    [Asked by Shelby Nagwitz]

A You might think a POD type is a data type that arrives from outer space wrapped in a green protective covering, but POD stands for Plain Old Data and that's just what a POD type is. The exact definition is rather gnarly (see the C++ ISO standard), but the basic idea is that POD types contain primitive data compatible with C. For example, structs and ints are POD types, but a class with a user-defined constructor or virtual function is not. POD types have no virtual functions, base classes, user-defined constructors, copy constructors, assignment operator, or destructor.

To conceptualize POD types you can copy them by copying their bits. Also, POD types can be uninitialized. For example:

	struct RECT r; // value undefined
	POINT *ppoints = new POINT[100]; // ditto
	CString s; // calls ctor ==> not POD

PS: "ditto" means "The same as stated above or before"

Non-POD types usually require initialization, whether by calling a default (compiler-supplied) constructor or your own.

In the old days, POD was important mostly for people writing compilers or C++ programs compatible with C. Nowadays, POD comes up in the context of .NET. In managed C++, managed types (both __value and __gc) can contain embedded native POD types. Figure 3 shows code that illustrates this. The managed Circle class can contain a POINT but not a CPoint. If you try to compile pod.cpp, you'll get error C3633: "Cannot define 'm_center' as a member of managed 'Circle' because of the presence of default constructor 'CPoint::CPoint' on class 'CPoint'."


Figure 3 Pod.cpp
/////////////////////////////////////////////////////////////////////
// You can embed native POD types in a managed (__gc or __value) type.
// Compile with cl /clr.

#using <mscorlib.dll>

// simple struct is a POD type
struct POINT {
   int x;
   int y;
};

// native class w/ctor: not POD!
class CPoint : public POINT {
   CPoint() { x=y=0; }
};

// Managed __gc type
__gc class Circle {
public:
   POINT center;        // ok: embedded POD type
   CPoint m_center;     // Error: not POD!
   int radius;
};

接著在C++STANDARD-ISOIEC14882-1998 [§5.3.4, ¶15]

所以「Singleton* obj = new Singleton;」與「Singleton* obj = new Singleton();」有差別嗎?

Ans : No


參考文獻

1.    Implementing the Singleton Design Pattern
       http://www.inquiry.com/techtips/cpp_pro/10min/10min0200.asp

2.    Use private copy constructor and assignment operator to avoid object copying
        http://www.devx.com/tips/Tip/12570

3.    C++ Q&A Calling Virtual Functions, Persisting View State, POD Type -- MSDN Magazine, November 2004
        http://msdn.microsoft.com/msdnmag/issues/04/11/CQA/default.aspx

4.    POD Plain Ol' Data
        http://www.fnal.gov/docs/working-groups/fpcltf/Pkg/ISOcxx/doc/POD.html

5.    C++STANDARD-ISOIEC14882-1998
        http://www.ishiboo.com/~nirva/c++/C++STANDARD-ISOIEC14882-1998.pdf

6.    ditto - definition of ditto by the Free Online Dictionary, Thesaurus and Encyclopedia.
        http://www.thefreedictionary.com/ditto


回上一頁

Written By James Liang @ 2007/01/29

Hosted by www.Geocities.ws

1