在C++類中,編譯器能夠暗自爲class建立default構造函數、copy構造函數、copy assignment操做符,以及析構函數。注意,這些編譯器產生出來的函數都是public的,爲了阻止這些函數被建立出來,咱們能夠把它們聲明爲private,這樣就阻止了編譯器暗自建立其對應版本函數。c++
class Node { public: Node(int _data = 0) : data(_data) {} int get() const { return data; } void set(int _data) { data = _data; } private: Node(const Node &); Node &operator=(const Node &); int data; };
在上面的class定義中,當程序企圖拷貝Node對象時,編譯器就會阻止該操做。這樣的話,只要將copy構造函數和copy assign操做符聲明爲private就能夠了,還有另一種方式,咱們能夠專門定義一個阻止copying動做的base class。這個base class以下所示:函數
class Uncopyable { protected: Uncopyable() {} // 容許derived對象構造和析構 ~Uncopyable() {} private: Uncopyable(const Uncopyable &); // 阻止copying Uncopyable &operator=(const Uncopyable &); }; class Node : private Uncopyable { public: Node(int _data = 0) : data(_data) {} int get() const { return data; } void set(int _data) { data = _data; } private: int data; };
這樣的話,在程序中,甚至在member函數或friend函數中,嘗試拷貝Node對象,編譯器就會試着生成一個copy構造函數或copy assign操做符,這些函數的「默認版本」會嘗試調用其base class的對應函數,可是這些調用會被阻止,由於它們是private的,即阻止了該類對象的copy操做。學習
參考資料:spa
【1】 《Effective C++ 第3版》 條款6指針
而經過閱讀開源代碼學習能夠使用宏定義來禁止class的拷貝構造函數和賦值構造函數(如下代碼源於Apollo/modules/common/macro.h)code
宏定義 DISALLOW_COPY_AND_ASSIGN:對象
#define DISALLOW_COPY_AND_ASSIGN(classname) \ private: \ classname(const classname &); \ classname &operator=(const classname &);
用於在C++中禁止class的拷貝構造函數和賦值構造函數,良好的c++代碼應該主動管理這2個操做符。get
在caffe、cartographer和Apollo或者其餘的著名庫中均有相似的操做。編譯器
宏定義 DISALLOW_IMPLICIT_CONSTRUCTORS:編譯
#define DISALLOW_IMPLICIT_CONSTRUCTORS(classname) \ private: \ classname(); \ DISALLOW_COPY_AND_ASSIGN(classname);
禁止class的無參構造函數。
宏定義 DECLARE_SINGLETON:
#define DECLARE_SINGLETON(classname) \ public: \ static classname *instance() { \ static classname instance; \ return &instance; \ } \ DISALLOW_IMPLICIT_CONSTRUCTORS(classname) \ private:
單例類定義,instance() 返回指向同一個class對象的指針。禁止拷貝/賦值運算符。