effective c++(05)(06)之c++默默編寫並調用的函數

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操做符以及析構函數。

相關文章
相關標籤/搜索