再探C++的單件實現 (轉)

worldblog發表於2007-12-12
再探C++的單件實現 (轉)[@more@]

最近看了adrianx的大作《C++實現單件的初探》,真是講得很好,不過裡面有一處疏漏。

現對其Singleton類的設計分析如下:

首先,讓我們來對Singleton類進行如下測試:

#include
using namespace std;

// 為了給Singleton類的Instance計數
template
class Counter
{
public:
  Counter() { ++count; }
  ~Counter() { --count; }

  Counter(const Counter&) { ++count; }
 
  static size_t HowMany()
  { return count; }

private:
  static size_t count;
};

class Singleton : private Counter
{
private:
  Singleton()
  {
  cout<  }
public:
  using Counter::HowMany; // Added by jfwan

  ~Singleton()
  {
  cout<"<  }

  static Singleton & GetSingleton()
  {
  static Singleton s;
  return s;
  }
  void Dosomething()
  {
  cout<  }
};

int main(int argc, char* argv[])
{
  Singleton& first = Singleton::GetSingleton();

  Singleton second(first);  // 1

  Singleton third(first);  // 2

  cout << "There are " << Singleton::HowMany()
  << " instances of Singleton." << endl;

  return 0;
}


結果:

object is [0049F1C0] Do< Construction
There are 3 instances of Singleton.
object is [0012FEB3] Do Destruction>
object is [0012FEBF] Do Destruction>
object is [0049F1C0] Do Destruction>

可以看出Singleton產生了三個Instance,但Construction卻只被了一次,不難看出另外兩個Instance是被Copy Ctor構造出來的,到此,我們已經找到了這段中的這個小小的了,但如何來去掉這隻‘臭蟲‘呢?

當我們不定義Copy Ctor時,在需要的時候會產生一個預設的Copy Ctor。分析上面的程式碼,對於Singleton Pattern,1,2兩處的用法應該被禁止,對於1,2這種情況來說是很容易的(但它確實應該被禁止掉)。但一旦在程式中有意或無意的使用了by-value的方式進行呼叫

,就不易被我們所發現。這種情況我們應該儘量使它們在compile-time暴露出來。我們可以透過將Destructor置於private section的方法使1,2不能在此定義。因為Singleton的Destructor屬於private section, Compiler將如是抱怨!於是...

但是對於某些類來說,Destructor並不是必需的,而且,有Destructor會降低performance(雖然那只是一點點,但既然我們能避免,又何樂而不為呢)。因此透過改變Destructor的Access level並不是十分明智!然而我們應該如何阻止諸如1,2之類的行為發生呢?Let me think...

嗯!我們得避免編譯器合成Default copy constructor行為的產生,然而怎樣才能達到這一目的呢?所幸的是,避免編譯器的這種幕後操作並不難。

且看修改後的Singleton類如下所示:

class Singleton : private Counter
{
  // 同上

private: // preventions
  Singleton(const Singleton&);
  Singleton& operator = (const Singleton&);
};

我將Singleton的Copy ctor和Assignment operator宣告為private, 並且不提供定義(這是為了避免被friend或member functions呼叫)。這樣我們就可以很明顯的使1,2出通不過Compiler!使得該Singleton類成為Singleton Pattern的比較完美的實現。

完整程式碼如下:

class Singleton
{
private:
  Singleton()
  {
  cout<  }
public:
  ~Singleton()
  {
  cout<"<  }

  static Singleton & GetSingleton()
  {
  static Singleton s;
  return s;
  }
  void Dosomething()
  {
  cout<  }

private: // preventions
  Singleton(const Singleton&);
  Singleton& operator = (const Singleton&);
};

至此,我們的Singleton類就設計完成了!其中難免還有遺漏之處,還望各位不吝指教!

to:jfwan@vip.sina.com">jfwan@vip.sina.com


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-991705/,如需轉載,請註明出處,否則將追究法律責任。

相關文章