轉自:WebKit中的設計模式(一): Noncopyable
WebKit作為一款優秀的瀏覽器,其中有著非常優秀的設計,值得我們借鑒。本文的目的就是剖析WebKit中值得借鑒的設計模式,瞭解其設計思想,以達到能為我們使用的目的。關於設計模式,推薦閱讀經典書籍<<設計模式-可複用物件導向軟體的基礎>>。本文所分析的設計模式,並非全部都是書上所提及的設計模式。因為設計模式是一個非常泛的概念,只要能夠重複使用且能解決特定問題的設計,應該都可以算作設計模式,希望朋友們不要較真。
言歸正傳,首先我們來分析以下WebKit中Noncopyable的使用。在閱讀WebKit的源碼過程中,發現很多類都繼承了Noncopyable類。我們來看看Noncopyable的定義:
namespace WTFNoncopyable {
class Noncopyable {
Noncopyable(const Noncopyable&);
Noncopyable& operator=(const Noncopyable&);
protected:
Noncopyable() { }
~Noncopyable() { }
};
} // namespace WTFNoncopyable
using WTFNoncopyable::Noncopyable;
Noncopyable類非常簡單,就是將拷貝建構函式和=操作符定義成私人。這樣做的目的是什麼呢?
我們知道,如果我們沒有為類定義拷貝建構函式和賦值操作f符,編譯器會自動為我們提供拷貝建構函式和賦值操作符。所以下面的代碼可以正常工作:
class A {
int a;
};
int main(int argc, char* argv[])
{
A x;
A xx(a);
A xxx = a;
}
問題在於,編譯器提供的拷貝建構函式只是進行"淺"拷貝,考慮下面的代碼會碰到什麼問題?
class A {
char *a;
public:
A{ a = (char*)malloc(10);}
~A{free(a);
};
int main(int argc, char* argv[])
{
A x;
A xx(a);
}
因為x和xx的a欄位指標指向同一個地址,這樣對象銷毀是,存在兩次釋放同一指標的問題。如何避免這種問題呢,一種方法是加上說明,提醒類的使用者本類不能進行拷貝構造和賦值操作,這顯然不是一個好的解決方案,另外一種方法是禁止訪問它的拷貝建構函式和賦值操作符(可以將拷貝建構函式和賦值操作符方法設為私人或保護)。WebKit中給出了一個更好的解決方案,就是定義Noncopyable基類,從Noncopyable類派生的類預設不能進行拷貝構造和賦值操作。但也並非完全禁止拷貝構造和賦值操作,只要我們顯示的提供拷貝建構函式和賦值操作,對象還是可以進行拷貝構造和賦值操作,但這是在我們的控制之下。
在其它庫中我們也可以看到這樣的設計,比如boost庫也定義了一個boost::noncopyable類。