C++(七):如何定義類(基礎(chǔ))

在c++中珊燎,可以使用類定義自己的數(shù)據(jù)類型。類的基本思想是數(shù)據(jù)抽象封裝粟焊。數(shù)據(jù)抽象是一種依賴于接口和實現(xiàn)分離的編程技術(shù)。

類的接口包括用戶所能執(zhí)行的操作担锤;類的實現(xiàn)規(guī)則包括類的數(shù)據(jù)成員、負(fù)責(zé)接口實現(xiàn)的函數(shù)體以及定義類所需的各種私有函數(shù)滤奈。

封裝實現(xiàn)了類的接口和實現(xiàn)的分離葵礼。封裝后隱藏了類的實現(xiàn)細(xì)節(jié)粗梭。

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

抽象數(shù)據(jù)類型不允許用戶直接訪問它的數(shù)據(jù)成員罩扇。

7.1.1 設(shè)計Sales_data類

Sales_data類的數(shù)據(jù)成員包括:

  • string類型的bookNo剿干,表示ISBN編號蜂怎;
  • unsigned類型的units_sold穆刻,表示某本書的銷量置尔;
  • double類型的revenue,表示這本書的總銷售輸入氢伟;

Sales_data類的接口應(yīng)該包含以下操作:

  • 一個isbn成員函數(shù)榜轿,用于返回對象的ISBN編號;
  • 一個combine成員函數(shù)朵锣,用于將一個Sales_data對象加到另一個對象上谬盐;
  • 一個名為add的函數(shù),執(zhí)行兩個Sales_data對象的加法诚些;
  • 一個read函數(shù)飞傀,將數(shù)據(jù)從istream讀入到Sales_data對象中;
  • 一個print函數(shù)诬烹,將Sales_data對象的值輸出到ostream中砸烦;

7.1.2 定義改進的Sales_data類

定義類的時候,需要在類函數(shù)體內(nèi)定義數(shù)據(jù)成員绞吁、成員函數(shù)和非成員接口函數(shù)幢痘。其中成員函數(shù)的聲明必須在類的內(nèi)部,定義在類的內(nèi)部和外部都可家破。而作為接口組成部分的非成員函數(shù)颜说,聲明和定義都在類的外部。

struct Sales_data {
    //數(shù)據(jù)成員
    string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
    //成員函數(shù)
    string isbn() const { return bookNo; };
    Sales_data& combine(const Sales_data&);
    double avg_price() const;
};
//Sales_data的非成員函數(shù)
Sales_data add(const Sales_data&, const Sales_data&);
ostream& print(ostream&, const Sales_data&);
istream& read(istream&, Sales_data&);

this:對于成員函數(shù)isbn()汰聋,它只返回了類的bookNo數(shù)據(jù)成員门粪,實際上返回的是當(dāng)前對象的數(shù)據(jù)成員。

const成員函數(shù):isbn函數(shù)的參數(shù)列表之后的const關(guān)鍵字烹困,其作用是修改隱式this指針的類型玄妈。在參數(shù)列表后的const表示this是一個指向常量的指針,這樣使用const的成員函數(shù)被稱為常量成員函數(shù)韭邓。

在類的外部定義成員函數(shù)措近,其中Sales_data::avg_price是作用域運算符,表示avg_price函數(shù)是屬于類的作用域內(nèi)女淑。

double Sales_data::avg_price() const {
    if (units_sold)
        return  revenue / units_sold;
    else
        return 0;
}

定義一個返回this對象的函數(shù)

Sales_data& Sales_data::combine(const Sales_data& rhs) {
    units_sold += rhs.units_sold;
    revenue += rhs.revenue;
    return *this;
}

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

類的作者常常需要一些輔助函數(shù)瞭郑,盡管這些函數(shù)定義的操作從概念上來說屬于類的接口的組成部分,但是實際上不屬于類本身鸭你。

定義read和print函數(shù)

istream& read(istream& is, Sales_data& item)
{
    double price = 0;
    is >> item.bookNo >> item.units_sold >> price;
    item.revenue = price * item.units_sold;
    return is;
}
ostream& print(ostream& os, const Sales_data& item)
{
    os << item.isbn() << "  " << item.units_sold << "  "
        << item.revenue << "  " << item.avg_price();
    return os;
}

定義add函數(shù)

Sales_data add(const Sales_data& lhs, const Sales_data& rhs)
{
    Sales_data sum = lhs;
    sum.combine(rhs);
    return sum;
}

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

每個類都通過構(gòu)造函數(shù)分別定義了它的對象被初始化的方法屈张,構(gòu)造函數(shù)的任務(wù)是初始化類對象的數(shù)據(jù)成員擒权,無論何時類被創(chuàng)建,都會執(zhí)行構(gòu)造函數(shù)阁谆。

構(gòu)造函數(shù)沒有返回類型碳抄,其形參列表可以為空也可由形參,函數(shù)體也可以為空也可有內(nèi)容场绿。類可以包含多個構(gòu)造函數(shù)剖效,和其他重載函數(shù)類似。

合成的默認(rèn)構(gòu)造函數(shù):如果一個類并沒定義任何構(gòu)造函數(shù)焰盗,則類通過一個特殊的構(gòu)造函數(shù)來控制默認(rèn)初始化過程璧尸,叫做默認(rèn)構(gòu)造函數(shù),由編譯器創(chuàng)建的構(gòu)造函數(shù)叫做合成的默認(rèn)構(gòu)造函數(shù)熬拒,如果存在類內(nèi)初始值就用它來初始化成員爷光,否則默認(rèn)初始化該成員。

合成的默認(rèn)構(gòu)造函數(shù)只適合非常簡單的類澎粟,一般都得定義自己的默認(rèn)構(gòu)造函數(shù)蛀序。默認(rèn)構(gòu)造函數(shù)即以自身的類名作為函數(shù)名。

    //構(gòu)造函數(shù)
    Sales_data() = default;
    Sales_data(const string &s):bookNo(s){}
    Sales_data(const string &s ,unsigned n, double p):
        bookNo(s),units_sold(n),revenue(p*n){}
    Sales_data(istream&);

Sales_data() = default:該構(gòu)造函數(shù)不接受任何實參活烙,所以它是個默認(rèn)構(gòu)造函數(shù)徐裸,定義該構(gòu)造函數(shù)的目的僅僅是因為需要其它形式的構(gòu)造函數(shù)。

第二和第三個構(gòu)造函數(shù)中出現(xiàn)了新的部分:冒號和花括號之間的代碼瓣颅,該部分被稱為構(gòu)造函數(shù)初始值列表倦逐,其中花括號定義了空的函數(shù)體,負(fù)責(zé)為新創(chuàng)建的對象的一個或幾個數(shù)據(jù)成員賦初值宫补。

第三個構(gòu)造函數(shù)的定義在類的外部檬姥。定義構(gòu)造函數(shù)時必須指明該構(gòu)造函數(shù)時哪個類的成員。

調(diào)用各構(gòu)造函數(shù)的代碼如下:

Sales_data total;
Sales_data t1("10001-100");
Sales_data t2("10001-100",5,30.5);
Sales_data t3(cin);

7.1.5 拷貝粉怕、賦值和析構(gòu)

除了類的對象初始化之外健民,還需要控制拷貝、賦值和銷毀對象時發(fā)生的行為贫贝。如果沒有主動定義這些操作秉犹,編譯器將合成它們。比如沒有定義賦值語句稚晚,就會將各個數(shù)據(jù)成員進行賦值崇堵。

7.2 訪問控制與封裝

在C++中,可以使用訪問說明符來加強類的封裝性客燕。

  • 定義在public說明符之后的成員在整個程序內(nèi)可被訪問鸳劳,public成員定義類的接口
  • 定義在private說明符之后的成員可以被類的成員函數(shù)訪問,但是不能被使用該類的代碼發(fā)昂我也搓,private封裝了類的實現(xiàn)細(xì)節(jié)

class關(guān)鍵字和struct關(guān)鍵字都可以用來定義類赏廓,但是class關(guān)鍵字在第一個訪問說明符之前的成員都是private的涵紊,而struct關(guān)鍵字在第一個訪問說明符之前的成員都是public的。

7.2.1 友元

如果類的數(shù)據(jù)成員是private的幔摸,則在函數(shù)外定義的類的接口無法正常編譯摸柄。如果想讓其他類或者函數(shù)訪問它的非公有成員,就應(yīng)該令其他類和函數(shù)稱為他的友元既忆,如下:

class Sales_data{
    //為類的非成員函數(shù)做的友元聲明
    friend Sales_data add(const Sales_data&, const Sales_data&);
    friend istream &read(istream&, Sales_data&);
    friend ostream &print(ostream&, const Sales_data&);
    public:
        Sales_data()=defult;
        ...
    private:
    string bookNo;
    unsigned units_sold=0;
    double revenue=0.0;
}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末驱负,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子尿贫,更是在濱河造成了極大的恐慌电媳,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件庆亡,死亡現(xiàn)場離奇詭異,居然都是意外死亡捞稿,警方通過查閱死者的電腦和手機又谋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來娱局,“玉大人彰亥,你說我怎么就攤上這事∷テ耄” “怎么了任斋?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長耻涛。 經(jīng)常有香客問我废酷,道長,這世上最難降的妖魔是什么抹缕? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任澈蟆,我火速辦了婚禮,結(jié)果婚禮上卓研,老公的妹妹穿的比我還像新娘趴俘。我一直安慰自己,他們只是感情好奏赘,可當(dāng)我...
    茶點故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布寥闪。 她就那樣靜靜地躺著,像睡著了一般磨淌。 火紅的嫁衣襯著肌膚如雪疲憋。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天伦糯,我揣著相機與錄音柜某,去河邊找鬼嗽元。 笑死,一個胖子當(dāng)著我的面吹牛喂击,可吹牛的內(nèi)容都是我干的剂癌。 我是一名探鬼主播,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼翰绊,長吁一口氣:“原來是場噩夢啊……” “哼佩谷!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起监嗜,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤谐檀,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后裁奇,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體桐猬,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年刽肠,在試婚紗的時候發(fā)現(xiàn)自己被綠了溃肪。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡音五,死狀恐怖惫撰,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情躺涝,我是刑警寧澤厨钻,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站坚嗜,受9級特大地震影響夯膀,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜惶傻,卻給世界環(huán)境...
    茶點故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一棍郎、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧银室,春花似錦涂佃、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至抓狭,卻和暖如春伯病,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工午笛, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留惭蟋,地道東北人。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓药磺,卻偏偏與公主長得像告组,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子癌佩,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,675評論 2 359

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