最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

C++ Primer 筆記-第7章 類(lèi)

2022-12-09 20:47 作者:Code有毒  | 我要投稿
  1. 類(lèi)的基本思想是:數(shù)據(jù)抽象 data abstraction?和?封裝 encapsulation。

  2. 數(shù)據(jù)抽象?是一種依賴(lài)于?接口 interface?和?實(shí)現(xiàn) implementation?分離的編程(以及設(shè)計(jì))技術(shù)。

  3. 類(lèi)的?接口?包括用戶(hù)所能執(zhí)行的操作;類(lèi)的?實(shí)現(xiàn)?則包括類(lèi)的數(shù)據(jù)成員、負(fù)責(zé)接口實(shí)現(xiàn)的函數(shù)體以及定義類(lèi)所需的各種私有函數(shù)。

  4. 封裝?實(shí)現(xiàn)了類(lèi)的接口和實(shí)現(xiàn)的分離。封裝后的類(lèi)隱藏了它的實(shí)現(xiàn)細(xì)節(jié),類(lèi)的用戶(hù)只能使用接口而無(wú)法訪(fǎng)問(wèn)實(shí)現(xiàn)部分。

7.1 定義抽象數(shù)據(jù)類(lèi)型

7.1.2 定義改進(jìn)的?Sales_data?類(lèi)

  1. 成員函數(shù)通過(guò)一個(gè)名為?this?的額外隱式參數(shù)來(lái)訪(fǎng)問(wèn)調(diào)用它的那個(gè)對(duì)象。當(dāng)調(diào)用一個(gè)成員函數(shù)時(shí),用請(qǐng)求該函數(shù)的對(duì)象地址初始化?this

struct Sales_data {

? std::string isbn() const {return bookNo;} ? // 隱式inline

? std::string bookNo; }

Sales_data total;

total.isbn();

// 編譯器負(fù)責(zé)把 total 的地址傳遞給 isbn() 的隱式形參 this

// 可以等價(jià)地認(rèn)為編譯器將該調(diào)用重寫(xiě)成了:

Sales_data::isbn(&total); ? // 偽代碼

  1. 任何自定義名為?this?的參數(shù)或變量的行為都是非法的。

  2. this?是個(gè)常量指針,初始化該指針之后,不再允許改變?this?中保存的地址。例如在?Sales_data?成員函數(shù)中,this?的類(lèi)型是?Sales_data *const(頂層?const)。

  3. this?是隱式的而且不會(huì)出現(xiàn)在參數(shù)列表中,所以在哪里將?this?聲明成指向常量的指針就是我們需要面對(duì)的問(wèn)題。C++語(yǔ)言的做法是允許把?const?關(guān)鍵字放在成員函數(shù)的參數(shù)列表之后,此時(shí)?this?是一個(gè)指向常量對(duì)象的常量指針(const Sales_data *const this),向這樣使用?const?的成員函數(shù)被稱(chēng)作?常量成員函數(shù)。

// 偽代碼:

std::string Sales_data::isbn(const Sales_data *const this) {

? return this->bookNo;

}

7.1.3 定義類(lèi)相關(guān)的非成員函數(shù)

  1. IO類(lèi)屬于不能被拷貝的類(lèi)型,因此我們只能通過(guò)引用來(lái)傳遞它們。

7.2 訪(fǎng)問(wèn)控制與封裝

  1. 使用?class?和?struct?定義類(lèi)的唯一的區(qū)別就是默認(rèn)的訪(fǎng)問(wèn)權(quán)限。

7.2.1 友元

  1. 類(lèi)可以允許其他類(lèi)或者函數(shù)訪(fǎng)問(wèn)它的非公有成員,方式是令其他類(lèi)或者函數(shù)成為它的?友元 friend

  2. 封裝有兩個(gè)重要的優(yōu)點(diǎn):

    · 確保用戶(hù)代碼不會(huì)無(wú)意間破壞封裝對(duì)象的狀態(tài)。

    · 被封裝的類(lèi)的具體實(shí)現(xiàn)細(xì)節(jié)可以隨時(shí)改變,而無(wú)須調(diào)整用戶(hù)級(jí)別的代碼

7.3 類(lèi)的其他特性

7.3.1 類(lèi)成員再探

  1. 一個(gè)?可變數(shù)據(jù)成員 mutable data member?(通過(guò)在變量的聲明中加入?mutable?關(guān)鍵字)永遠(yuǎn)不會(huì)是?const, 即使它是?const?對(duì)象的成員。因此,一個(gè)?const?成員函數(shù)可以改變一個(gè)可變成員的值。

  2. 當(dāng)提供一個(gè)類(lèi)內(nèi)初始值時(shí),必須以符號(hào)?=?或者?{}?表示。

7.3.3 類(lèi)類(lèi)型

  1. 因?yàn)橹挥挟?dāng)類(lèi)全部完成后類(lèi)才算被定義,所以一個(gè)類(lèi)的成員類(lèi)型不能是該類(lèi)自己。然而,一旦一個(gè)類(lèi)的名字出現(xiàn)后,它就被認(rèn)為是聲明過(guò)了(但尚未定義),因此類(lèi)允許包含指向它自身類(lèi)型的引用或指針。

7.3.4 友元再探

  1. 友元關(guān)系不具有傳遞性。

  2. 如果一個(gè)類(lèi)想把一組重載函數(shù)聲明成它的友元,它需要對(duì)這組函數(shù)中的每一個(gè)函數(shù)分別聲明。

7.4 類(lèi)的作用域

  1. 當(dāng)我們?cè)陬?lèi)的外部定義成員函數(shù)時(shí),必須同時(shí)提供類(lèi)名和函數(shù)名。一旦遇到了類(lèi)名,定義的剩余部分就在類(lèi)的作用域之內(nèi)了,這里的剩余部分包括參數(shù)列表和函數(shù)體,此時(shí)我們可以直接使用類(lèi)的其他成員而無(wú)需再次授權(quán)。但是函數(shù)的返回類(lèi)型通常出現(xiàn)在函數(shù)名的前面,此時(shí)返回類(lèi)型中使用的名字都位于類(lèi)的作用域之外,所以必須聲明它是哪個(gè)類(lèi)的成員。

class Screen{}

class Window_mgr {

public:

? using ScreenIndex = std::vector<Screen>::size_type;

? ScreenIndex addScreen(const Screen&); ? ?

}

Window_mgr::ScreenIndex Window_mgr::addScreen(const Screen& s){}

7.4.1 名字查找與類(lèi)的作用域

  1. 編譯器處理完類(lèi)中的全部聲明后才會(huì)處理成員函數(shù)的定義。

  2. 一般來(lái)說(shuō),內(nèi)層作用域可以重新定義外層作用域的名字,即使該名字已經(jīng)在內(nèi)層作用域中使用過(guò)。然而在類(lèi)中,如果成員使用了外層作用域中的某個(gè)名字,而該名字代表一種類(lèi),則類(lèi)不能在之后重新定義該名字:

typedef double Money;

class Account {

public:

? ?Money balance(){ return bal; } ?// 使用外層作用域的Money

private:

? typedef double Money; ? ? ? ? ? // 錯(cuò)誤:不能重新定義 Money

? Money bal;

}

  1. 即使?Account?中定義的?Money?類(lèi)型與外層作用域一致,上述代碼仍然是錯(cuò)誤的。但是編譯器并不為此負(fù)責(zé),一些編譯器仍將順利通過(guò)這樣的代碼,而忽略代碼錯(cuò)誤的事實(shí)。

  2. 類(lèi)型名的定義通常出現(xiàn)在類(lèi)的開(kāi)始處,這樣就能確保所有使用該類(lèi)型的成員都出現(xiàn)在類(lèi)名的定義之后。

7.5 構(gòu)造函數(shù)再探

7.5.1 構(gòu)造函數(shù)初始值列表

  1. 成員的初始化順序與它們?cè)陬?lèi)定義中出現(xiàn)順序一致。盡量避免使用某些成員初始化其他成員。

7.5.2 委托構(gòu)造函數(shù)

  1. C++11 新標(biāo)準(zhǔn)擴(kuò)展了構(gòu)造函數(shù)初始值的功能,使得我們可以定義所謂的?委托構(gòu)造函數(shù) delegating constructor。一個(gè)委托構(gòu)造函數(shù)使用它所屬類(lèi)的其他構(gòu)造函數(shù)執(zhí)行它自己的初始化過(guò)程,或者說(shuō)它把它自己的一些(或者全部)職責(zé)委托給了其他構(gòu)造函數(shù)。

class Sales_data {

public:

? // 非委托構(gòu)造函數(shù)

? Sales_data(int a) {

? ? ? // 實(shí)現(xiàn)a

? }

? // 委托構(gòu)造函數(shù),該函數(shù)會(huì)先調(diào)用實(shí)現(xiàn)a,然后再調(diào)用實(shí)現(xiàn)b

? Sales_data(): Sales_data(0) {

? ? ? ?// 實(shí)現(xiàn)b

? }

}

7.5.4 隱式的類(lèi)類(lèi)型轉(zhuǎn)換

  1. 如果構(gòu)造函數(shù)只接受一個(gè)實(shí)參,則它實(shí)際上定義了轉(zhuǎn)換為此類(lèi)類(lèi)型的隱式轉(zhuǎn)換機(jī)制,稱(chēng)為?轉(zhuǎn)換構(gòu)造函數(shù)converting constructor。

  2. 編譯器值會(huì)自動(dòng)地執(zhí)行一步類(lèi)型轉(zhuǎn)換。如該調(diào)用需類(lèi)型轉(zhuǎn)換多次,則應(yīng)使用顯示類(lèi)型轉(zhuǎn)換。

  3. 使用?explicit?關(guān)鍵字聲明構(gòu)造函數(shù)時(shí),該構(gòu)造函數(shù)只能以直接初始化的形式使用,且編譯器將不會(huì)在自動(dòng)轉(zhuǎn)換過(guò)程中使用該構(gòu)造函數(shù)。

std::string str;

Sales_data item1(str); ?// 正確:直接初始化

Sales_data item2 = str; // 錯(cuò)誤,不能用于拷貝形式的初始化過(guò)程。

  1. 關(guān)鍵字?explicit?只對(duì)一個(gè)實(shí)參的構(gòu)造函數(shù)有效。只能在類(lèi)內(nèi)聲明構(gòu)造函數(shù)時(shí)使用,在類(lèi)外部定義時(shí)不應(yīng)重復(fù)。

  2. 盡管編譯器不會(huì)將?explicit?的構(gòu)造函數(shù)用于隱式轉(zhuǎn)換過(guò)程,但是我們可以使用?Sales_data(str)?或者?static_cast<Sales_data>(str)?這兩種方式顯示地強(qiáng)制進(jìn)行轉(zhuǎn)換。

7.5.5 聚合類(lèi)

  1. 聚合類(lèi) aggregate class?只含有公有成員的類(lèi),并且沒(méi)有類(lèi)內(nèi)初始值或者構(gòu)造函數(shù)。聚合類(lèi)的成員可以用花括號(hào)括起來(lái)的初始值列表進(jìn)行初始化。

7.5.7 字面值常量類(lèi)

  1. 數(shù)據(jù)成員都是字面值類(lèi)型的聚合類(lèi)是字面值常量類(lèi)。

  2. 如果一個(gè)類(lèi)不是聚合類(lèi),但是它符合下述要求,它也是一個(gè)字面值常量類(lèi):

    · 數(shù)據(jù)成員都必須是字面值類(lèi)型。 · 類(lèi)必須至少含有一個(gè)?constexpr?構(gòu)造函數(shù)。 · 如果一個(gè)數(shù)據(jù)成員含有類(lèi)內(nèi)初始值,則內(nèi)置類(lèi)型成員的初始值必須是一條常量表達(dá)式;或者如果成員屬于某種類(lèi)類(lèi)型,則初始值必須使用成員自己的?constexpr?構(gòu)造函數(shù)。 · 類(lèi)必須使用析構(gòu)函數(shù)的默認(rèn)定義,該成員負(fù)責(zé)銷(xiāo)毀類(lèi)的對(duì)象。

  3. constexpr?構(gòu)造函數(shù)體一般來(lái)說(shuō)應(yīng)該是空。且必須初始化所有數(shù)據(jù)成員。

class Debug {

public:

? constexpr Debug(bool b = true) : hw(b), io(b), other(b){}

? constexpr Debug(bool h, bool i, bool o) : hw(h), io(i), other(o){}

? constexpr bool any() { return hw || io || other; }

private:

? bool hw;

? bool io;

? bool other;

}

constexpr Debug io_sub(false, true, false);

constexpr Debug prod(false);

io_sub.any();

prod.any();


7.6 類(lèi)的靜態(tài)成員

  1. 有的時(shí)候類(lèi)需要它的一些成員與類(lèi)本身直接相關(guān),而不是與類(lèi)的各個(gè)對(duì)象保持關(guān)聯(lián)。

  2. 類(lèi)的靜態(tài)成員存在于任何對(duì)象之外,對(duì)象中不包含任何于靜態(tài)數(shù)據(jù)成員有關(guān)的數(shù)據(jù)。類(lèi)的靜態(tài)成員對(duì)象只有一個(gè),且被所有該類(lèi)對(duì)象共享。

  3. 靜態(tài)成員函數(shù)也不于任何對(duì)象綁定在一起,它們不包含?this?指針。不能聲明成?const。這一限制既適用于?this?的顯示使用,也對(duì)調(diào)用?非靜態(tài)成員的隱式使用?有效。

  4. 因?yàn)殪o態(tài)數(shù)據(jù)成員不屬于類(lèi)的任何一個(gè)對(duì)象,所以它們并不是在創(chuàng)建類(lèi)的對(duì)象時(shí)被定義的。這意味著它們不是由類(lèi)的構(gòu)造函數(shù)初始化的,必須在類(lèi)的外部定義和初始化每個(gè)靜態(tài)成員,且一個(gè)靜態(tài)數(shù)據(jù)成員只能定義一次。一旦它被定義,就將一直存在于程序的整個(gè)生命周期中。

  5. 要想確保對(duì)象只定義一次,最好的辦法是把靜態(tài)數(shù)據(jù)成員的定義與其他非內(nèi)聯(lián)函數(shù)的定義放在同一個(gè)文件中。

  6. 通常類(lèi)的靜態(tài)成員不應(yīng)該在類(lèi)的內(nèi)部初始化。然而,我們可以為靜態(tài)成員提供?const?整數(shù)類(lèi)型的類(lèi)內(nèi)初始值,不過(guò)要求靜態(tài)成員必須是字面值常量類(lèi)型的?constexpr

class Account {

private:

? static constexpr int period = 30;

}

// 即使在類(lèi)內(nèi)部被初始化了,通常情況下也應(yīng)該在類(lèi)的外不定義一下該成員。

constexpr int Account::period;

  1. 靜態(tài)數(shù)據(jù)成員的類(lèi)型可以就是它所屬的類(lèi)類(lèi)型。而非靜態(tài)數(shù)據(jù)成員則受到限制,只能聲明成它所屬類(lèi)的指針或引用。

  2. 可以使用靜態(tài)數(shù)據(jù)成員作為成員函數(shù)的默認(rèn)實(shí)參。非靜態(tài)數(shù)據(jù)成員則不能,因?yàn)榉庆o態(tài)數(shù)據(jù)成員本身屬于對(duì)象的一部分,無(wú)法提供一個(gè)對(duì)象以便從中獲取成員的值,最終將引發(fā)錯(cuò)誤。


C++ Primer 筆記-第7章 類(lèi)的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
伊金霍洛旗| 朝阳市| 呼伦贝尔市| 辛集市| 崇阳县| 临邑县| 玉树县| 攀枝花市| 鹤岗市| 邯郸市| 西丰县| 广宁县| 清丰县| 突泉县| 紫阳县| 安陆市| 梅河口市| 潼关县| 安义县| 台中县| 贺州市| 犍为县| 正阳县| 井陉县| 崇文区| 陵水| 璧山县| 吉林省| 舒城县| 礼泉县| 响水县| 宝坻区| 朝阳区| 彰化县| 疏勒县| 灵璧县| 叙永县| 海原县| 宁城县| 云南省| 新竹县|