C++類總結(jié)

本文博客園地址:http://www.cnblogs.com/xiongxuanwen/p/4290086.html

一、C++類的定義

C++中使用關(guān)鍵字class來定義類, 其基本形式如下:

class 類名

{

public:

//行為或?qū)傩?/a>

protected:

//行為或?qū)傩?/a>

private:

//行為或?qū)傩?/a>

};

示例:

定義一個(gè)點(diǎn)(Point)類, 具有以下屬性和方法:

■ 屬性: x坐標(biāo), y坐標(biāo)

■ 方法: 1.設(shè)置x,y的坐標(biāo)值; 2.輸出坐標(biāo)的信息。

實(shí)現(xiàn)代碼:

class Point

{

public:

void setPoint(int x, int y);

void printPoint();

private:

int xPos;

int yPos;

};

代碼說明:

上段代碼中定義了一個(gè)名為 Point 的類, 具有兩個(gè)私密屬性, int型的xPos和yPos, 分別用來表示x點(diǎn)和y點(diǎn)。

在方法上,setPoint用來設(shè)置屬性, 也就是 xPos 和 yPos 的值;printPoint用來輸出點(diǎn)的信息。

1 數(shù)據(jù)抽象和封裝

抽象是通過特定的實(shí)例抽取共同特征以后形成概念的過程。一個(gè)對(duì)象是現(xiàn)實(shí)世界中一個(gè)實(shí)體的抽象,一個(gè)類是一組對(duì)象的抽象。

封裝是將相關(guān)的概念組成一個(gè)單元,然后通過一個(gè)名稱來引用它。面向?qū)ο蠓庋b是將數(shù)據(jù)和基于數(shù)據(jù)的操作封裝成一個(gè)整體對(duì)象,對(duì)數(shù)據(jù)的訪問或修改只能通過對(duì)象對(duì)外提供的接口進(jìn)行。

2 類定義

幾個(gè)重要名詞:

(1) 類名

遵循一般的命名規(guī)則; 字母,數(shù)字和下劃線組合,不要以數(shù)字開頭。

(2) 類成員

類可以沒有成員,也可以定義多個(gè)成員。成員可以是數(shù)據(jù)、函數(shù)或類型別名。所有的成員都必須在類的內(nèi)部聲明。

沒有成員的類是空類,空類也占用空間。

class?People

{

};

sizeof(People) = 1;

(3) 構(gòu)造函數(shù)

構(gòu)造函數(shù)是一個(gè)特殊的、與類同名的成員函數(shù),用于給每個(gè)數(shù)據(jù)成員設(shè)置適當(dāng)?shù)某跏贾怠?/p>

(4) 成員函數(shù)

成員函數(shù)必須在類內(nèi)部聲明,可以在類內(nèi)部定義,也可以在類外部定義。如果在類內(nèi)部定義,就默認(rèn)是內(nèi)聯(lián)函數(shù)。

3 類定義補(bǔ)充

3.1 可使用類型別名來簡(jiǎn)化類

除了定義數(shù)據(jù)和函數(shù)成員之外,類還可以定義自己的局部類型名字。

使用類型別名有很多好處,它讓復(fù)雜的類型名字變得簡(jiǎn)單明了、易于理解和使用,還有助于程序員清楚地知道使用該類型的真實(shí)目的。

classPeople

{

public:

typedef std::stringphonenum;//電話號(hào)碼類型

phonenumphonePub; //公開號(hào)碼

private:

phonenumphonePri;//私人號(hào)碼

};

3.2?成員函數(shù)可被重載

可以有多個(gè)重載成員函數(shù),個(gè)數(shù)不限。

3.3內(nèi)聯(lián)函數(shù)

有三種:

(1)直接在類內(nèi)部定義。

(2)在類內(nèi)部聲明,加上inline關(guān)鍵字,在類外部定義。

(3)在類內(nèi)部聲明,在類外部定義,同時(shí)加上inline關(guān)鍵字。注意:此種情況下,內(nèi)聯(lián)函數(shù)的定義通常應(yīng)該放在類定義的同一頭文件中,而不是在源文件中。這是為了保證內(nèi)聯(lián)函數(shù)的定義在調(diào)用該函數(shù)的每個(gè)源文件中是可見的。

3.4 訪問限制

public,private,protected為屬性/方法限制的關(guān)鍵字。

3.5 類的數(shù)據(jù)成員中不能使用 auto、extern和register等進(jìn)行修飾, 也不能在定義時(shí)進(jìn)行初始化

int xPos = 0;?//錯(cuò);

例外:

靜態(tài)常量整型(包括char,bool)數(shù)據(jù)成員可以直接在類的定義體中進(jìn)行初始化,例如:

static const int ia= 30;

4 類聲明與類定義

4.1 類聲明(declare)

classScreen;

在聲明之后,定義之前,只知道Screen是一個(gè)類名,但不知道包含哪些成員。只能以有限方式使用它,不能定義該類型的對(duì)象,只能用于定義指向該類型的指針或引用,聲明(不是定義)使用該類型作為形參類型或返回類型的函數(shù)。

void Test1(Screen& a){};

void Test1(Screen* a){};

4.2 類定義(define)

在創(chuàng)建類的對(duì)象之前,必須完整的定義該類,而不只是聲明類。所以,類不能具有自身類型的數(shù)據(jù)成員,但可以包含指向本類的指針或引用。

classLinkScreen

{

public:

Screen?window;

LinkScreen* next;

LinkScreen* prev;

};//注意,分號(hào)不能丟

因?yàn)樵陬惗x之后可以接一個(gè)對(duì)象定義列表,可類比內(nèi)置類型,定義必須以分號(hào)結(jié)束:

classLinkScreen{ /* ... */ };

classLinkScreen{ /* ... */ } scr1,scr2;

5 類對(duì)象

定義類對(duì)象時(shí),將為其分配存儲(chǔ)空間。

Sales_item item;//編譯器分配了足以容納一個(gè) Sales_item 對(duì)象的存儲(chǔ)空間。item 指的就是那個(gè)存儲(chǔ)空間。

6 隱含的 this 指針

成員函數(shù)具有一個(gè)附加的隱含形參,即?this指針,它由編譯器隱含地定義。成員函數(shù)的函數(shù)體可以顯式使用 this 指針。

6.1 何時(shí)使用 this 指針

當(dāng)我們需要將一個(gè)對(duì)象作為整體引用而不是引用對(duì)象的一個(gè)成員時(shí)。最常見的情況是在這樣的函數(shù)中使用 this:該函數(shù)返回對(duì)調(diào)用該函數(shù)的對(duì)象的引用。

class Screen

{

...

public:

Screen& set(char);

};

Screen& Screen::set(char c)

{

contents[cursor] = c;

return *this;

}

7?類作用域

每個(gè)類都定義了自己的作用域和唯一的類型。

類的作用域包括:類的內(nèi)部(花括號(hào)之內(nèi)), 定義在類外部的成員函數(shù)的參數(shù)表(小括號(hào)之內(nèi))和函數(shù)體(花括號(hào)之內(nèi))。

class Screen

{

//類的內(nèi)部

...

};

//類的外部

char Screen::get(index r, index c) const

{

index row = r * width;????? // compute the row location

return contents[row + c];?? // offset by c to fetch specified?character

}

注意:成員函數(shù)的返回類型不一定在類作用域中??赏ㄟ^ 類名::來判斷是否是類的作用域,::之前不屬于類的作用域,::之后屬于類的作用域。例如

Screen:: 之前的返回類型就不在類的作用域,Screen:: 之后的函數(shù)名開始到函數(shù)體都是類的作用域。

class Screen

{

public:

typedef std::string::size_type index;

indexget_cursor() const;

};

Screen::indexScreen::get_cursor() const ? //注意:index前面的Screen不能少

{

return cursor;

}

該函數(shù)的返回類型是 index,這是在 Screen 類內(nèi)部定義的一個(gè)類型名。在類作用域之外使用,必須用完全限定的類型名 Screen::index 來指定所需要的 index 是在類 Screen 中定義的名字。

二 構(gòu)造函數(shù)

構(gòu)造函數(shù)是特殊的成員函數(shù),用來保證每個(gè)對(duì)象的數(shù)據(jù)成員具有合適的初始值。

構(gòu)造函數(shù)名字與類名相同,不能指定返回類型(也不能定義返回類型為void),可以有0-n個(gè)形參。

在創(chuàng)建類的對(duì)象時(shí),編譯器就運(yùn)行一個(gè)構(gòu)造函數(shù)。

1 構(gòu)造函數(shù)可以重載

可以為一個(gè)類聲明的構(gòu)造函數(shù)的數(shù)量沒有限制,只要每個(gè)構(gòu)造函數(shù)的形參表是唯一的。

class Sales_item;

{

public:

Sales_item(const std::string&);

Sales_item(std::istream&);

Sales_item(); //默認(rèn)構(gòu)造函數(shù)

};

2 構(gòu)造函數(shù)自動(dòng)執(zhí)行

只要?jiǎng)?chuàng)建該類型的一個(gè)對(duì)象,編譯器就運(yùn)行一個(gè)構(gòu)造函數(shù):

Sales_item item1("0-201-54848-8");

Sales_item *p = new Sales_item();

第一種情況下,運(yùn)行接受一個(gè) string 實(shí)參的構(gòu)造函數(shù),來初始化變量item1。

第二種情況下,動(dòng)態(tài)分配一個(gè)新的 Sales_item 對(duì)象,通過運(yùn)行默認(rèn)構(gòu)造函數(shù)初始化該對(duì)象。

3 構(gòu)造函數(shù)初始化式

與其他函數(shù)一樣,構(gòu)造函數(shù)具有名字、形參表和函數(shù)體。

與其他函數(shù)不同的是,構(gòu)造函數(shù)可以包含一個(gè)構(gòu)造函數(shù)初始化列表

Sales_item::Sales_item(const string &book):isbn(book), units_sold(0), revenue(0.0)

{ }

構(gòu)造函數(shù)初始化列表以一個(gè)冒號(hào)開始,接著是一個(gè)以逗號(hào)分隔的數(shù)據(jù)成員列表,每個(gè)數(shù)據(jù)成員后面跟一個(gè)放在圓括號(hào)中的初始化式。

構(gòu)造函數(shù)可以定義在類的內(nèi)部或外部。構(gòu)造函數(shù)初始化只在構(gòu)造函數(shù)的定義中指定。

構(gòu)造函數(shù)分兩個(gè)階段執(zhí)行:(1)初始化階段;(2)普通的計(jì)算階段。初始化列表屬于初始化階段(1),構(gòu)造函數(shù)函數(shù)體中的所有語句屬于計(jì)算階段(2)。

初始化列表比構(gòu)造函數(shù)體先執(zhí)行。不管成員是否在構(gòu)造函數(shù)初始化列表中顯式初始化,類類型的數(shù)據(jù)成員總是在初始化階段初始化。

3.1 哪種類需要初始化式

const 對(duì)象或引用類型的對(duì)象,可以初始化,但不能對(duì)它們賦值,而且在開始執(zhí)行構(gòu)造函數(shù)的函數(shù)體之前要完成初始化。

初始化 const 或引用類型數(shù)據(jù)成員的唯一機(jī)會(huì)是構(gòu)造函數(shù)初始化列表中,在構(gòu)造函數(shù)函數(shù)體中對(duì)它們賦值不起作用。

沒有默認(rèn)構(gòu)造函數(shù)的類類型的成員,以及 const 或引用類型的成員,必須在初始化列表中完成初始化。

class ConstRef

{

public:

ConstRef(int ii);

private:

int i;

constint ci;

int &ri;

};

ConstRef::ConstRef(int ii)

{

i = ii; ? // ok

ci = ii; ?// error

ri = i; ? //

}

應(yīng)該這么初始化:

ConstRef::ConstRef(int ii): i(ii), ci(i), ri(ii) { }

3.2 成員初始化的次序

每個(gè)成員在構(gòu)造函數(shù)初始化列表中只能指定一次。重復(fù)初始化,編譯器一般會(huì)有提示。

成員被初始化的次序就是定義成員的次序,跟初始化列表中的順序無關(guān)。

3.3 初始化式表達(dá)式

初始化式可以是任意表達(dá)式

Sales_item(const std::string &book, int cnt, doubleprice): isbn(book), units_sold(cnt), revenue(cnt * price) { }

3.4 類類型的數(shù)據(jù)成員的初始化式

初始化類類型的成員時(shí),要指定實(shí)參并傳遞給成員類型的一個(gè)構(gòu)造函數(shù),可以使用該類型的任意構(gòu)造函數(shù)。

Sales_item(): isbn(10, '9'), units_sold(0), revenue(0.0) {}

3.5?類對(duì)象的數(shù)據(jù)成員的初始化

在類A的構(gòu)造函數(shù)初始化列表中沒有顯式提及的每個(gè)成員,使用與初始化變量相同的規(guī)則來進(jìn)行初始化。

類類型的數(shù)據(jù)成員,運(yùn)行該類型的默認(rèn)構(gòu)造函數(shù)來初始化。

內(nèi)置或復(fù)合類型的成員的初始值依賴于該類對(duì)象的作用域:在局部作用域中不被初始化,在全局作用域中被初始化為0。假設(shè)有一個(gè)類A,

class A

{

public:

int ia;

B b;

};

A類對(duì)象A a;不管a在局部作用域還是全局作用域,b使用B類的默認(rèn)構(gòu)造函數(shù)來初始化,ia的初始化取決于a的作用域,a在局部作用域,ia不被初始化,a在全局作用域,ia初始化0。

4 默認(rèn)構(gòu)造函數(shù)

不含形參的構(gòu)造函數(shù)就是默認(rèn)構(gòu)造函數(shù)。

只要定義一個(gè)對(duì)象時(shí)沒有提供初始化式,就使用默認(rèn)構(gòu)造函數(shù)。如: A a;

為所有形參提供默認(rèn)實(shí)參的構(gòu)造函數(shù)也定義了默認(rèn)構(gòu)造函數(shù)。例如:

class A

{

public:

A(int a=1,char c =''){}

private:

int ia;

char c1;

};

4.1 合成的默認(rèn)構(gòu)造函數(shù)

只有當(dāng)一個(gè)類沒有定義構(gòu)造函數(shù)時(shí),編譯器才會(huì)自動(dòng)生成一個(gè)默認(rèn)構(gòu)造函數(shù)。

一個(gè)類只要定義了一個(gè)構(gòu)造函數(shù),編譯器也不會(huì)再生成默認(rèn)構(gòu)造函數(shù)。

建議:

如果定義了其他構(gòu)造函數(shù),也提供一個(gè)默認(rèn)構(gòu)造函數(shù)。

如果類包含內(nèi)置或復(fù)合類型(如 int& 或 string*)的成員,它應(yīng)該定義自己的構(gòu)造函數(shù)來初始化這些成員。每個(gè)構(gòu)造函數(shù)應(yīng)該為每個(gè)內(nèi)置或復(fù)合類型的成員提供初始化。

5 隱式類類型轉(zhuǎn)換

5.1?只含單個(gè)形參的構(gòu)造函數(shù)能夠?qū)崿F(xiàn)從形參類型到該類類型的一個(gè)隱式轉(zhuǎn)換

class A

{

public:

A(int a)

{

ia =a;

}

bool EqualTo(const A& a)

{

return ia == a.ia;

}

private:

int ia;

};

A a(1);

bool bEq = false;

bEq =a.EqualTo(1);//參數(shù)為1,實(shí)現(xiàn)從int型到A的隱式轉(zhuǎn)換

5.2抑制由構(gòu)造函數(shù)定義的隱式轉(zhuǎn)換

通過將構(gòu)造函數(shù)聲明為explicit,來防止在需要隱式轉(zhuǎn)換的上下文中使用構(gòu)造函數(shù):

class A

{

public:

explicitA(int a )

{

ia =a;

}

bool EqualTo(const A& a)

{

return ia == a.ia;

}

private:

int ia;

};

通常,除非有明顯的理由想要定義隱式轉(zhuǎn)換,否則,單形參構(gòu)造函數(shù)應(yīng)該為 explicit。將構(gòu)造函數(shù)設(shè)置為 explicit 可以避免錯(cuò)誤。

三 復(fù)制控制

1 復(fù)制構(gòu)造函數(shù)

1.1 幾個(gè)要點(diǎn)

(1) 復(fù)制構(gòu)造函數(shù)

復(fù)制構(gòu)造函數(shù)是一種特殊構(gòu)造函數(shù),只有1個(gè)形參,該形參(常用 const &修飾)是對(duì)該類類型的引用。

class Peopel

{

public:

Peopel();//默認(rèn)構(gòu)造函數(shù)

Peopel(const Peopel&);//復(fù)制構(gòu)造函數(shù)

~Peopel();//析構(gòu)函數(shù)

};

當(dāng)定義一個(gè)新對(duì)象并用一個(gè)同類型的對(duì)象對(duì)它進(jìn)行初始化時(shí),將顯式使用復(fù)制構(gòu)造函數(shù)。

Peopel?a1;?Peopel?a2 = a1;

當(dāng)將該類型的對(duì)象傳遞給函數(shù)或函數(shù)返回該類型的對(duì)象時(shí),將隱式使用復(fù)制構(gòu)造函數(shù)。

Peopel?Func(Peopel?b){...}

(2)析構(gòu)函數(shù)

析構(gòu)函數(shù)是構(gòu)造函數(shù)的互補(bǔ):當(dāng)對(duì)象超出作用域或動(dòng)態(tài)分配的對(duì)象被刪除時(shí),將自動(dòng)應(yīng)用析構(gòu)函數(shù)。

析構(gòu)函數(shù)可用于釋放構(gòu)造對(duì)象時(shí)或在對(duì)象的生命期中所獲取的資源。

不管類是否定義了自己的析構(gòu)函數(shù),編譯器都自動(dòng)執(zhí)行類中非 static 數(shù)據(jù)成員的析構(gòu)函數(shù)。

(3) 復(fù)制控制

復(fù)制構(gòu)造函數(shù)、賦值操作符和析構(gòu)函數(shù)總稱為復(fù)制控制。編譯器自動(dòng)實(shí)現(xiàn)這些操作,但類也可以定義自己的版本。

(4)?兩種初始化形式

C++ 支持兩種初始化形式:直接初始化和復(fù)制初始化。直接初始化將初始化式放在圓括號(hào)中,復(fù)制初始化使用 = 符號(hào)。

對(duì)于內(nèi)置類型,例如int, double等,直接初始化和復(fù)制初始化沒有區(qū)別。

對(duì)于類類型:直接初始化直接調(diào)用與實(shí)參匹配的構(gòu)造函數(shù);復(fù)制初始化先使用指定構(gòu)造函數(shù)創(chuàng)建一個(gè)臨時(shí)對(duì)象,然后用復(fù)制構(gòu)造函數(shù)將那個(gè)臨時(shí)對(duì)象復(fù)制到正在創(chuàng)建的對(duì)象。直接初始化比復(fù)制初始化更快。

(5)形參和返回值

當(dāng)形參或返回值為類類型時(shí),由該類的復(fù)制構(gòu)造函數(shù)進(jìn)行復(fù)制。

(6)初始化容器元素

復(fù)制構(gòu)造函數(shù)可用于初始化順序容器中的元素。例如:

vector svec(5);

編譯器首先使用 string 默認(rèn)構(gòu)造函數(shù)創(chuàng)建一個(gè)臨時(shí)值,然后使用復(fù)制構(gòu)造函數(shù)將臨時(shí)值復(fù)制到 svec 的每個(gè)元素。

(7)構(gòu)造函數(shù)與數(shù)組元素

如果沒有為類類型數(shù)組提供元素初始化式,則將用默認(rèn)構(gòu)造函數(shù)初始化每個(gè)元素。

如果使用常規(guī)的花括號(hào)括住的數(shù)組初始化列表來提供顯式元素初始化式,則使用復(fù)制初始化來初始化每個(gè)元素。根據(jù)指定值創(chuàng)建適當(dāng)類型的元素,然后用復(fù)制構(gòu)造函數(shù)將該值復(fù)制到相應(yīng)元素:

Sales_item primer_eds[] = { string("0-201-16487-6"),

string("0-201-54848-8"),

string("0-201-82470-1"),

Sales_item()

};

1.2?合成的復(fù)制構(gòu)造函數(shù)

(1)合成的復(fù)制構(gòu)造函數(shù)

如果沒有定義復(fù)制構(gòu)造函數(shù),編譯器就會(huì)為我們合成一個(gè)。

合成復(fù)制構(gòu)造函數(shù)的行為是,執(zhí)行逐個(gè)成員初始化,將新對(duì)象初始化為原對(duì)象的副本。

逐個(gè)成員初始化:合成復(fù)制構(gòu)造函數(shù)直接復(fù)制內(nèi)置類型成員的值,類類型成員使用該類的復(fù)制構(gòu)造函數(shù)進(jìn)行復(fù)制。

例外:如果一個(gè)類具有數(shù)組成員,則合成復(fù)制構(gòu)造函數(shù)將復(fù)制數(shù)組。復(fù)制數(shù)組時(shí)合成復(fù)制構(gòu)造函數(shù)將復(fù)制數(shù)組的每一個(gè)元素。

1.3 定義自己的復(fù)制構(gòu)造函數(shù)

(1) 只包含類類型成員或內(nèi)置類型(但不是指針類型)成員的類,無須顯式地定義復(fù)制構(gòu)造函數(shù),也可以復(fù)制。

class Peopel

{

public:

std::string name;

unsigned int id;

unsigned int age;

std::string address;

};

(2) 有些類必須對(duì)復(fù)制對(duì)象時(shí)發(fā)生的事情加以控制。

例如,類有一個(gè)數(shù)據(jù)成員是指針,或者有成員表示在構(gòu)造函數(shù)中分配的其他資源。而另一些類在創(chuàng)建新對(duì)象時(shí)必須做一些特定工作。這兩種情況下,都必須定義自己的復(fù)制構(gòu)造函數(shù)。

最好顯式或隱式定義默認(rèn)構(gòu)造函數(shù)和復(fù)制構(gòu)造函數(shù)。如果定義了復(fù)制構(gòu)造函數(shù),必須定義默認(rèn)構(gòu)造函數(shù)。

1.4 禁止復(fù)制

有些類需要完全禁止復(fù)制。例如,iostream 類就不允許復(fù)制。延伸:容器內(nèi)元素不能為iostream

為了防止復(fù)制,類必須顯式聲明其復(fù)制構(gòu)造函數(shù)為 private。

2 賦值操作符

與復(fù)制構(gòu)造函數(shù)一樣,如果類沒有定義自己的賦值操作符,則編譯器會(huì)合成一個(gè)。

(1)重載賦值操作符

Sales_item&operator=(const Sales_item &);

(2)合成賦值操作符

合成賦值操作符會(huì)逐個(gè)成員賦值:右操作數(shù)對(duì)象的每個(gè)成員賦值給左操作數(shù)對(duì)象的對(duì)應(yīng)成員。除數(shù)組之外,每個(gè)成員用所屬類型的常規(guī)方式進(jìn)行賦值。對(duì)于數(shù)組,給每個(gè)數(shù)組元素賦值。

(3)復(fù)制和賦值常一起使用

一般而言,如果類需要復(fù)制構(gòu)造函數(shù),它也會(huì)需要賦值操作符。

3 析構(gòu)函數(shù)

構(gòu)造函數(shù)的用途之一是自動(dòng)獲取資源;與之相對(duì)的是,析構(gòu)函數(shù)的用途之一是回收資源。除此之外,析構(gòu)函數(shù)可以執(zhí)行任意類設(shè)計(jì)者希望在該類對(duì)象的使用完畢之后執(zhí)行的操作。

(1) 何時(shí)調(diào)用析構(gòu)函數(shù)

撤銷(銷毀)類對(duì)象時(shí)會(huì)自動(dòng)調(diào)用析構(gòu)函數(shù)。

變量(類對(duì)象)在超出作用域時(shí)應(yīng)該自動(dòng)撤銷(銷毀)。

動(dòng)態(tài)分配的對(duì)象(new A)只有在指向該對(duì)象的指針被刪除時(shí)才撤銷(銷毀)。

撤銷(銷毀)一個(gè)容器(不管是標(biāo)準(zhǔn)庫(kù)容器還是內(nèi)置數(shù)組)時(shí),也會(huì)運(yùn)行容器中的類類型元素的析構(gòu)函數(shù)(容器中的元素總是從后往前撤銷)。

(2)何時(shí)編寫顯式析構(gòu)函數(shù)

如果類需要定義析構(gòu)函數(shù),則它也需要定義賦值操作符和復(fù)制構(gòu)造函數(shù),這個(gè)規(guī)則常稱為三法則:如果類需要析構(gòu)函數(shù),則需要所有這三個(gè)復(fù)制控制成員。

(3)合成析構(gòu)函數(shù)

合成析構(gòu)函數(shù)按對(duì)象創(chuàng)建時(shí)的逆序撤銷每個(gè)非 static 成員,因此,它按成員在類中聲明次序的逆序撤銷成員。

對(duì)于每個(gè)類類型的成員,合成析構(gòu)函數(shù)調(diào)用該成員的析構(gòu)函數(shù)來撤銷對(duì)象。

合成析構(gòu)函數(shù)并不刪除指針成員所指向的對(duì)象。 所以,如果有指針成員,一定要定義自己的析構(gòu)函數(shù)來刪除指針。

析構(gòu)函數(shù)與復(fù)制構(gòu)造函數(shù)或賦值操作符之間的一個(gè)重要區(qū)別:即使我們編寫了自己的析構(gòu)函數(shù),合成析構(gòu)函數(shù)仍然運(yùn)行。

四 友元

友元機(jī)制允許一個(gè)類將對(duì)其非公有成員的訪問權(quán)授予指定的函數(shù)。

友元可以出現(xiàn)在類定義的內(nèi)部的任何地方。

友元不是授予友元關(guān)系的那個(gè)類的成員,所以它們不受聲明出現(xiàn)部分的訪問控制影響。

建議:將友元聲明成組地放在類定義的開始或結(jié)尾。

1 友元類

class Husband

{

public:

friendclass Wife;

private:

double money;//錢是老公私有的,別人不能動(dòng),但老婆除外

};

class Wife

{

public:

void Consume(Husband& h)

{

h.money -= 10000;//老婆可以花老公的錢

}

};

Husband h;

Wife w;

w.Consume(h);

2?使其他類的成員函數(shù)成為友元

class Husband;//1.聲明Husband

class Wife//2.定義Wife類

{

public:

void Consume(Husband& h);

};

class Husband//3.定義Husband類

{

public:

friend void Wife::Consume(Husband& h);//聲明Consume函數(shù)。

private:

double money;//錢是老公私有的,別人不能動(dòng),但老婆除外

};

void Wife::Consume(Husband& h)//4.定義Consume函數(shù)。

{

h.money -= 10000;//老婆可以花老公的錢

}

注意類和函數(shù)的聲明和定義的順序:

(1)聲明類Husband

(2)定義類Wife,聲明Consume函數(shù)

(3)定義類Husband

(4)定義Consume函數(shù)。

五 static 類成員

static 成員,有全局對(duì)象的作用,但又不破壞封裝。

1 static 成員變量

static 數(shù)據(jù)成員是與類關(guān)聯(lián)的對(duì)象,并不與該類的對(duì)象相關(guān)聯(lián)。

static 成員遵循正常的公有/私有訪問規(guī)則。

2 使用 static 成員而不是全局對(duì)象有三個(gè)優(yōu)點(diǎn)。

(1) ?static 成員的名字是在類的作用域中,因此可以避免與其他類的成員或全局對(duì)象名字沖突。

(2) ?可以實(shí)施封裝。static 成員可以是私有成員,而全局對(duì)象不可以。

(3) ?通過閱讀程序容易看出 static 成員是與特定類關(guān)聯(lián)的,這種可見性可清晰地顯示程序員的意圖。

3 static 成員函數(shù)

在類的內(nèi)部聲明函數(shù)時(shí)需要添加static關(guān)鍵字,但是在類外部定義函數(shù)時(shí)就不需要了。

因?yàn)閟tatic 成員是類的組成部分但不是任何對(duì)象的組成部分,所以有以下幾個(gè)特點(diǎn):

1) static 函數(shù)沒有 this 指針

2) static 成員函數(shù)不能被聲明為 const (將成員函數(shù)聲明為 const 就是承諾不會(huì)修改該函數(shù)所屬的對(duì)象)

3) static 成員函數(shù)也不能被聲明為虛函數(shù)

4 static 數(shù)據(jù)成員

static 數(shù)據(jù)成員可以聲明為任意類型,可以是常量、引用、數(shù)組、類類型,等等。

static 數(shù)據(jù)成員必須在類定義體的外部定義(正好一次),并且應(yīng)該在定義時(shí)進(jìn)行初始化。

建議:定義在類的源文件中名,即與類的非內(nèi)聯(lián)函數(shù)的定義同一個(gè)文件中。注意,定義時(shí)也要帶上類類型+"::"

double Account::interestRate = 0.035;

5 特殊的靜態(tài)常量整型成員

靜態(tài)常量整型數(shù)據(jù)成員可以直接在類的定義體中進(jìn)行初始化,例如:

static const int period = 30;

當(dāng)然char 可以轉(zhuǎn)換成整形,也是可以的,staticconst charbkground= '#';

6 其他

(1)static 數(shù)據(jù)成員的類型可以是該成員所屬的類類型。非 static 成員只能是自身類對(duì)象的指針或引用

classScreen

{

public:

// ...

private:

staticScreen src1; // ok

Screen?*src2;?????? // ok

Screen?src3;??????? // error

};

(2)非 static 數(shù)據(jù)成員不能用作默認(rèn)實(shí)參,static 數(shù)據(jù)成員可用作默認(rèn)實(shí)參

class Screen

{

public:

Screen& clear(char =bkground);

private:

staticconst charbkground= '#';//static const整形變量可以在類內(nèi)部初始化。

};

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,702評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,143評(píng)論 3 415
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,553評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,620評(píng)論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,416評(píng)論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,940評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,024評(píng)論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,170評(píng)論 0 287
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,709評(píng)論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,597評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,784評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,291評(píng)論 5 357
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,029評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,407評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,663評(píng)論 1 280
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,403評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,746評(píng)論 2 370

推薦閱讀更多精彩內(nèi)容

  • 前言 把《C++ Primer》[https://book.douban.com/subject/25708312...
    尤汐Yogy閱讀 9,531評(píng)論 1 51
  • C++文件 例:從文件income. in中讀入收入直到文件結(jié)束,并將收入和稅金輸出到文件tax. out。 檢查...
    SeanC52111閱讀 2,812評(píng)論 0 3
  • 一個(gè)博客,這個(gè)博客記錄了他讀這本書的筆記,總結(jié)得不錯(cuò)?!渡疃忍剿鰿++對(duì)象模型》筆記匯總 1. C++對(duì)象模型與內(nèi)...
    Mr希靈閱讀 5,605評(píng)論 0 13
  • 1. 讓自己習(xí)慣C++ 條款01:視C++為一個(gè)語言聯(lián)邦 為了更好的理解C++,我們將C++分解為四個(gè)主要次語言:...
    Mr希靈閱讀 2,830評(píng)論 0 13
  • 事情不多,心情不好。 今天沒有什么任務(wù)。早上特別困。沒太干啥,感覺得了空調(diào)病了,眼睛感覺特別干。下午提起一點(diǎn)精神...
    小不點(diǎn)Fight閱讀 178評(píng)論 0 0