1. 當只寫一個空類的時候,編譯器會爲他聲明一個copy構造函數,一個copy assignment函數和一個析構函數。以下:c++
若是寫下:函數
class Empty{ };
編譯器就會實現如下代碼:spa
class Empty{ Empty(){} //默認構造函數 Empty(const Empty& rhs ) {} //複製構造函數
~Empty() {} //析構函數 Empty& operator=( const Empty& rhs ) {} // 複製賦值操做符
};
編譯器產生的是non-virtual函數。默認產生以上四種構造函數。code
若是要使這些編譯器默認產生的函數失效則提供瞭如下兩種方法:對象
一. 將這些函數聲明爲private。以下:blog
class Empty{ public: private: Empty(const Empty& rhs ) {} };
此時若是進行以下調用:編譯器
Empty e1; Empty e2(e1); return 0;
編譯器就不會容許。可是這種狀況在member函數或者friend函數內進行的時候就能夠作到。string
二. 爲了可以保證全部的成員以及類不可以拷貝對象,須要定義如下類:編譯
class Uncopyable{ protected: Uncopyable() {} ~Uncopyable(){} private: Uncopyable( const Uncopyable& ); Uncopyable& operator=( const Uncopyable& ); };
而後使class
class Empty:private Uncopyable{ ....... };
這樣,當任何人(甚至是member函數或者friend函數)嘗試拷貝Empty對象時,編譯器試着生成一個copy構造函數和一個copy assignment操做符,而這些函數卻嘗試着調用base class對應的兄弟,此時編譯器便拒絕操做。
2.
class NamedObject{ public: NamedObject( const char* name, const T& value ); NamedObject( const string& name, const T& value ); private: string nameValue; T objectValue; };
NamedObject<int> no1( "Smallest Prim Number", 2 ); NamedObject<int> no2(no1);
編譯器已經爲NamedObject類定義了copy構造函數,因此 NamedObject<int> no2(no1) 就調用了該copy構造函數。
3.
template< typename T > class NamedObject{ public: NamedObject( const string& name, const T& value ); private: string& nameValue; const T objectValue; };
string newDog("persephone"); string oldDog("Satch"); NamedObject<int> p( newDog, 2 ); NamedObject<int> s( oldDog, 36 ); p = s;
c++不容許「讓reference」指向不一樣的對象。若是打算在一個內含有「reference」成員的class內支持賦值操做,必需要定義一個copy assignment操做符。一樣對於內含const的成員的類,更改const也是不合法的。
4. 若是某個base class將copy assignment聲明爲private,編譯器也拒絕爲其derived classes生成copy assignment操做符。由於編譯器爲derived classes生成的copy assignment操做符能夠處理base class成分。
總結:編譯器能夠暗自爲class建立default構造函數,copy構造函數,copy assignment操做符以及析構函數。