在 C++ 中,使用類定義自己的數(shù)據(jù)類型。
通過定義新的類型來反映待解決問題中的各種概念掌唾,可以使我們更容易編寫半夷、調(diào)試、修改程序。
類的基本思想使數(shù)據(jù)抽象和封裝。
數(shù)據(jù)抽象是一種依賴于接口和實(shí)現(xiàn)分離的編程技術(shù)。
類接口包括用戶所能執(zhí)行的操作际乘。類的實(shí)現(xiàn)則包括類的數(shù)據(jù)成員、負(fù)責(zé)接口實(shí)現(xiàn)的函數(shù)體以及定義類所需的各種私有函數(shù)漂佩。
封裝實(shí)現(xiàn)了類的接口和實(shí)現(xiàn)的分離脖含。封裝后的類隱藏了它的實(shí)現(xiàn)細(xì)節(jié)。用戶只能使用接口而無法訪問實(shí)現(xiàn)部分投蝉。
類想要實(shí)現(xiàn)數(shù)據(jù)抽象和封裝养葵,需要定義一個(gè)抽象數(shù)據(jù)類型,在抽象數(shù)據(jù)類型中瘩缆,由類的設(shè)計(jì)者負(fù)責(zé)考慮類的實(shí)現(xiàn)過程关拒。使用該類的程序員則只需要抽象地思考類型做了什么,無需了解類型的工作細(xì)節(jié)庸娱。
在第一章使用的 Sales_item 類是一個(gè)抽象數(shù)據(jù)類型着绊,可以通過它的接口來使用一個(gè) Sales_item 對(duì)象。 我們不能訪問 Sales_item 對(duì)象的數(shù)據(jù)成員熟尉,也根本不知道這個(gè)類有哪些數(shù)據(jù)成員归露。
Sales_data 類不是一個(gè)抽象數(shù)據(jù)類型。它允許類的用戶直接訪問它的數(shù)據(jù)成員并要求由用戶來編寫操作斤儿。若想把 Sales_data變成抽象數(shù)據(jù)類型剧包,需要定義一些操作以供類的用戶使用。一旦 Sales_data 定義了它自己的操作往果,就可以封裝它的數(shù)據(jù)成員了疆液。
最終目的是令 Sales_data 支持與 Sales_item 類完全一樣的操作集合。
Sales_item 類有名為 isbn 的成員函數(shù)陕贮。且支持 +堕油、=、+=、<<馍迄、>>運(yùn)算符福也。
再賦予 Sales_data 一個(gè)除 combine 和 isbn 外的另一個(gè)成員函數(shù) avg_price 用于返回售出書記的平均價(jià)格。因?yàn)槠洳⒎峭ㄓ门嗜Γ运鼞?yīng)該屬于類的實(shí)現(xiàn)的一部分,而非接口的一部分峦甩。
定義和聲明成員函數(shù)的方法與普通函數(shù)差不多赘来。成員函數(shù)的聲明必須在類的內(nèi)部,它的定義則既可以在類的內(nèi)部也可以在類的外部凯傲。作為接口組成部分而非成員函數(shù)犬辰。
盡管所有成員都必須在類的內(nèi)部聲明,但是成員函數(shù)體可以定義在類內(nèi)也可以定義在類外冰单。
isbn 函數(shù)幌缝,它的參數(shù)列表為空,返回值是一個(gè) string 對(duì)象:
成員函數(shù)體是一個(gè)塊诫欠,塊中只有一條 return 語句涵卵,用于返回 Sales_data 對(duì)象的 bookNo 數(shù)據(jù)成員。? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
我們使用了點(diǎn)運(yùn)算符來訪問 total 對(duì)象的 isbn? ? 成員荒叼,然后調(diào)用它轿偎。 total.isbn
成員函數(shù)通過一個(gè)名為 this 的額外隱式參數(shù)來訪問調(diào)用它的那個(gè)對(duì)象。當(dāng)調(diào)用一個(gè)成員函數(shù)時(shí)被廓,用請(qǐng)求該函數(shù)的對(duì)象地址初始化 this 坏晦。
可以將 isbn 定義成:std::string isbn() const {return this -> bookNo;}
因?yàn)?this 的目的總是指向 這個(gè) 對(duì)象,所以是一個(gè)常量指針嫁乘,不允許改成其保存的地址昆婿。
Isbn函數(shù)的另一個(gè)關(guān)鍵是緊隨參數(shù)列表之后的 const 關(guān)鍵字,在這里 const 的作用是修改隱式 this 指針的類型蜓斧。
默認(rèn)情況 this 的類型是指向類類型非常量版本的常量指針仓蛆。所以我們不能在一個(gè)常量對(duì)象上調(diào)用普通的成員函數(shù)。
把 const 關(guān)鍵字放在成員函數(shù)的參數(shù)列表之后法精,這樣使用 const 的成員函數(shù)被稱作常量成員函數(shù)多律。
isbn 的函數(shù)體
this 是指向常量的指針,所以常量成員函數(shù)不能改變調(diào)用它的對(duì)象內(nèi)容搂蜓。
常量對(duì)象狼荞、常量對(duì)象的引用或指針都只能調(diào)用常量成員函數(shù)。
類本身就是一個(gè)作用域帮碰,類的成員函數(shù)的定義嵌套在類的作用域內(nèi)相味。isbn 中用到的名字 bookNo 就是定義在 Sales_data 內(nèi)的數(shù)據(jù)成員。
即使 bookNo 定義在 isbn 之后殉挽,isbn 還是能夠使用 bookNo 丰涉。?
編譯器分兩步處理類:首先編譯成員的聲明拓巧,之后才輪到成員函數(shù)體。所以成員函數(shù)體可以任意使用類中的其它成員且無須在意這些成員出現(xiàn)的次序一死。
在類的外部定義成員函數(shù)時(shí)肛度,成員函數(shù)的定義必須與它的聲明匹配。返回類型投慈、參數(shù)列表承耿、函數(shù)名都與類內(nèi)部的聲明保持一致。
函數(shù) avg_price ()
avg_price 函數(shù)被聲明在類 Sales_data 的作用域內(nèi)伪煤。一旦編譯器看到這個(gè)函數(shù)名加袋,就能理解剩余的代碼是位于類的作用域內(nèi)的。
所以當(dāng)?avg_price 使用 revenue 抱既、units_sold 時(shí)职烧,實(shí)際它隱式地使用了 Sales_data 的成員。
函數(shù) combine 類似于復(fù)合運(yùn)算賦值運(yùn)算符 += 防泵。