C++ (七):類的具體細(xì)節(jié)

7.3 類的其他特性

除了前面介紹的簡單的類的特性,還有類型成員癌淮、類的成員的類內(nèi)初始值、可變數(shù)據(jù)成員沦补、內(nèi)聯(lián)成員函數(shù)乳蓄、從成員函數(shù)返回*this等。

7.3.1 類成員再探

如果需要定義一對相互關(guān)聯(lián)的類Screen和Window_mgr夕膀。

定義類型成員:除了定義數(shù)據(jù)和函數(shù)成員外虚倒,類還可以自定義某種類型在類中的別名。

class Screen {
public:
    typedef string::size_type pos;
private:
    pos cursor = 0;
    pos height = 0, width = 0;
    string contents;

};

Screen類的成員函數(shù):成員函數(shù)需有構(gòu)造函數(shù)和兩個成員函數(shù)产舞。

class Screen {
public:
    typedef string::size_type pos;
    Screen() = default;
    Screen(pos ht,pot wd,char c):height(ht),width(wd),
        contents(ht*wd,c){}
    char get() const{
        return contents[cursor];
    }
    inline char get(pos ht, pos wd)const;
    Screen& move(pos r, pos c);

private:
    pos cursor = 0;
    pos height = 0, width = 0;
    string contents;

};

inline 
Screen& Screen::move(pos r, pos c)
{
    pos row = r * width;
    cursor = row + c;
    return *this;
}
char  Screen::get(pos r, pos c)const
{
    pos row = r * width;
    return contents[row + c];
}

重載成員函數(shù): 與非成員函數(shù)一樣魂奥,成員函數(shù)也可被重載。

可變數(shù)據(jù)成員:如果希望能修改類的某一個數(shù)據(jù)成員易猫,即使是在一個const成員函數(shù)內(nèi)耻煤,也可通過在變量的聲明中加入mutable關(guān)鍵字。一個可變數(shù)據(jù)成員永遠(yuǎn)不會是const准颓,即使它是const對象的成員哈蝇,一個const成員函數(shù)可以改變一個可變成員的值。

class Screen {
public:
    void some_member() const;
private:
    mutable size_t access_ctr;
};
void Screen::some_member() const
{
    ++access_ctr;
}

類數(shù)據(jù)成員的初始值:定義好Screen類之后攘已,可以繼續(xù)定義一個窗口管理類并用它表示顯示器上的一組Screen炮赦。這個類將包含一個Screen類的vector。每個元素表示一個特定的Screen贯被,默認(rèn)情況下希望Window_mgr類總是擁有一個默認(rèn)初始化的Screen眼五,最好的方式就是把這個默認(rèn)值聲明成一個類內(nèi)初始值妆艘。

7.3.2 返回*this的成員函數(shù)

class Screen {
public:
    Screen& set(char);
    Screen& set(pos, pos, char);
};
inline Screen& Screen::set(char)
{
    contents[cursor] = c;
    return *this;
}
inline Screen& Screen::set(pos r, pos col, char ch)
{
    contents[r * width + col] = ch;
    return *this;
}

7.3.3 類類型

每個類都定義了唯一的類型,如果兩個類成員完全一樣看幼,那也是兩個不同的類型批旺。

類的聲明:類的聲明和定義也可分開,可以僅僅聲明類而暫時不定義它诵姜,這樣的聲明被稱作前向聲明汽煮。

7.3.4 友元再探

不僅一個函數(shù)可以為類的友元,一個類也可為另一個類的友元棚唆,但是友元不具有傳遞性暇赤。

令成員函數(shù)作為友元:除了令整個類作為一個類的友元以外,還可以只令該類的一個成員函數(shù)作為友元宵凌。

7.4 類的作用域

每個類都會定義自己的作用域鞋囊,在類的作用域之外,可以使用作用域運(yùn)算符來訪問瞎惫。

作用域和定義在類外部的成員:在類的外部定義成員函數(shù)時必須同時提供類名和函數(shù)名溜腐。遇到類名之后,定義的剩余部分就在類的作用域之中瓜喇。

void Window_mgr::clear(ScreenIndex i)
{
    Screen &s = screens[i];
    s.contents = string(s.height*s.width,' ');
}

但是函數(shù)的返回類型出現(xiàn)在函數(shù)名之前挺益,所以定義在類外部的成員函數(shù),必須先用作用域運(yùn)算符指明返回值時哪個類的成員乘寒。

class Window_mgr{
    public:
    ScreenIndex addScreen(const Screen&);
};
Window_mgr::ScreenIndex
Window_mgr::addScreen(const Screen &s)
{
    screens.push_back(s);
    return screens.size()-1;
}

7.4.1 名字查找與類的作用域

名字查找:

  • 首先望众,在名字所在塊中尋找其聲明語句,只考慮在名字的使用之前出現(xiàn)的聲明伞辛。
  • 如果沒找到烂翰,繼續(xù)查找外層作用域

在類中:

  • 首先,編譯成員的聲明
  • 直到類全部可見后才編譯函數(shù)體

用類成員聲明的名字查找: 如果在類成員聲明中就使用的返回類型始锚、形參類型刽酱,都必須在使用前確保可見瞧捌。

typedef double Money;
string bal;
class Account{
    public:
    Money balance() { return bal; }
    private:
    Money bal;
}

類型名要特殊處理:

一般內(nèi)層作用域可以重新定義外層作用域中的名字,在類中也一樣润文,但是如果類成員使用了外層作用域中的某個名字之后姐呐,則類不能在之后重新定義該名字。

成員定義中的普通塊作用域的名字查找:

  • 首先典蝌,在成員函數(shù)中查找該名字的聲明曙砂,只有在函數(shù)使用之前出現(xiàn)的聲明才被考慮
  • 如果在成員函數(shù)中未找到,則在類中繼續(xù)查找骏掀,此時類的所有成員都可以被考慮
  • 如果類內(nèi)也沒找到鸠澈,則在成員函數(shù)定義之前的作用域內(nèi)繼續(xù)查找柱告。

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

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

對于類所構(gòu)建的對象的數(shù)據(jù)成員而言,初始化與賦值有一定區(qū)別笑陈。如果沒有在構(gòu)造函數(shù)的初始值列表中顯式地初始化成員际度,則該成員將在構(gòu)造函數(shù)體之前進(jìn)行默認(rèn)初始化。

但是如果數(shù)據(jù)成員為const或者是引用及為提供默認(rèn)構(gòu)造函數(shù)的類類型時涵妥,必須在構(gòu)造函數(shù)時對其進(jìn)行初始化乖菱。

成員初始化的順序:構(gòu)造函數(shù)初始值列表只能說明用于初始化成員的值,而不限定初始化的具體執(zhí)行順序蓬网。一般順序不太重要窒所,但是如果用一個成員來對另外一個成員進(jìn)行初始化,就要考慮兩個成員的初始化順序帆锋,一般是依據(jù)聲明的順序進(jìn)行初始化吵取。

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

一個委托構(gòu)造函數(shù)使用它所屬類的其他構(gòu)造函數(shù)執(zhí)行它自己的初始化過程,或者它把自己的一些職責(zé)委托給了其他構(gòu)造函數(shù)锯厢。

與其他構(gòu)造函數(shù)一樣海渊,委托構(gòu)造函數(shù)也有成員初始值的列表和函數(shù)體。

class Sales_data{
    public:
    Sales_data(std::string s,unsigned cnt,double price):
        bookNo(s),units_sold(cnt),revenue(cnt*price){}
    Sales_data(): Sales_data(" ",0,0){}
    Sales_data(std::string s):Sales_data(s,0,0){}
    Sales_data(std::istream &is):Sales_data(){read(is,*this);}
}

7.5.3 默認(rèn)構(gòu)造函數(shù)的作用

當(dāng)對象被默認(rèn)初始化和或值初始化時會自動執(zhí)行默認(rèn)構(gòu)造函數(shù)哲鸳。默認(rèn)初始化在以下情況下發(fā)生:

  • 在塊作用域不使用任何初始值定義一個非靜態(tài)變量或數(shù)組時
  • 當(dāng)一個類還有類類型成員且使用合成的默認(rèn)構(gòu)造函數(shù)時
  • 當(dāng)類類型成員沒有在構(gòu)造函數(shù)初始值列表中顯式地初始化

值初始化在以下情況發(fā)生:

  • 在數(shù)組初始化的過程中如果提供的初始值數(shù)量小于數(shù)組大小時
  • 不使用初始值定義一個局部靜態(tài)變量時

所以類必須包含一個默認(rèn)構(gòu)造函數(shù)以便在上述情況下使用臣疑。

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

C++語言在內(nèi)置類型之間定義了幾種自動轉(zhuǎn)換規(guī)則,而我們也可為類定義隱式轉(zhuǎn)換規(guī)則徙菠。如果構(gòu)造函數(shù)只接受一個實(shí)參讯沈,那么它實(shí)際上定義了轉(zhuǎn)換為此類型的隱式轉(zhuǎn)換機(jī)制,叫做轉(zhuǎn)換構(gòu)造函數(shù)婿奔。

string null_book="9-999-99";
item.combine(null_book);

在程序中缺狠,編譯器會將string對象null_book隱式轉(zhuǎn)換為Sales_data對象,并將其傳遞給combine萍摊。

但是在隱式類型轉(zhuǎn)換中挤茄,只允許一步的類型轉(zhuǎn)換,如下程序則不能實(shí)現(xiàn)隱式類型轉(zhuǎn)換冰木。

item.combine("9-999-99");//錯誤
item.combine(string("9-999-999"));//正確
item.combine(Sales_data("9-999-99"));//正確

抑制構(gòu)造函數(shù)定義的隱式轉(zhuǎn)換:可以用關(guān)鍵詞explicit加在構(gòu)造函數(shù)之前穷劈,抑制其隱式類型轉(zhuǎn)換的功能。但是仍可以用其實(shí)現(xiàn)顯式類型轉(zhuǎn)換踊沸。

7.5.5 聚合類

聚合類可以讓用戶直接訪問其成員歇终,并具有特殊的初始化語法形式,它有如下條件:

  • 所有成員都是public的
  • 沒有定義任何構(gòu)造函數(shù)
  • 沒有類內(nèi)初始值
  • 沒有基類逼龟,也沒有virtual函數(shù)

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

有時類需要與其成員直接相關(guān)评凝,而不是與類的各個對象保持關(guān)聯(lián),所以可以用類的靜態(tài)成員來表示腺律。

在成員的聲明前加上關(guān)鍵字static就可使得其與類關(guān)聯(lián)在一起奕短,和其他成員一樣宜肉,靜態(tài)成員可以是public的或private的,且可以是常量翎碑、引用谬返、指針、類類型等

靜態(tài)成員函數(shù)也不與任何對象綁定在一起杈女,它們沒有this指針朱浴,且不能聲明成const的。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末达椰,一起剝皮案震驚了整個濱河市翰蠢,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌啰劲,老刑警劉巖梁沧,帶你破解...
    沈念sama閱讀 211,743評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蝇裤,居然都是意外死亡廷支,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評論 3 385
  • 文/潘曉璐 我一進(jìn)店門栓辜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來恋拍,“玉大人,你說我怎么就攤上這事藕甩∈└遥” “怎么了?”我有些...
    開封第一講書人閱讀 157,285評論 0 348
  • 文/不壞的土叔 我叫張陵狭莱,是天一觀的道長僵娃。 經(jīng)常有香客問我,道長腋妙,這世上最難降的妖魔是什么默怨? 我笑而不...
    開封第一講書人閱讀 56,485評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮骤素,結(jié)果婚禮上匙睹,老公的妹妹穿的比我還像新娘。我一直安慰自己谆甜,他們只是感情好垃僚,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,581評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著规辱,像睡著了一般。 火紅的嫁衣襯著肌膚如雪栽燕。 梳的紋絲不亂的頭發(fā)上罕袋,一...
    開封第一講書人閱讀 49,821評論 1 290
  • 那天改淑,我揣著相機(jī)與錄音,去河邊找鬼浴讯。 笑死朵夏,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的榆纽。 我是一名探鬼主播仰猖,決...
    沈念sama閱讀 38,960評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼奈籽!你這毒婦竟也來了饥侵?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,719評論 0 266
  • 序言:老撾萬榮一對情侶失蹤衣屏,失蹤者是張志新(化名)和其女友劉穎躏升,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體狼忱,經(jīng)...
    沈念sama閱讀 44,186評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡膨疏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,516評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了钻弄。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片佃却。...
    茶點(diǎn)故事閱讀 38,650評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖窘俺,靈堂內(nèi)的尸體忽然破棺而出饲帅,到底是詐尸還是另有隱情,我是刑警寧澤批销,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布洒闸,位于F島的核電站,受9級特大地震影響均芽,放射性物質(zhì)發(fā)生泄漏丘逸。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,936評論 3 313
  • 文/蒙蒙 一掀宋、第九天 我趴在偏房一處隱蔽的房頂上張望深纲。 院中可真熱鬧,春花似錦劲妙、人聲如沸湃鹊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽币呵。三九已至,卻和暖如春侨颈,著一層夾襖步出監(jiān)牢的瞬間余赢,已是汗流浹背芯义。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留妻柒,地道東北人扛拨。 一個月前我還...
    沈念sama閱讀 46,370評論 2 360
  • 正文 我出身青樓撒穷,卻偏偏與公主長得像肠仪,于是被迫代替她去往敵國和親孟辑。 傳聞我的和親對象是個殘疾皇子逗嫡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,527評論 2 349

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

  • Hi蟀伸!這里是山幺幺的c++ primer系列恕酸。寫這個系列的初衷是嘹吨,雖然在學(xué)校學(xué)習(xí)了c++妖混,但總覺得對這門語言了解不...
    山幺幺閱讀 293評論 0 1
  • 類 在c++中痹屹,可以使用類定義自己的數(shù)據(jù)類型章郁。類的基本思想是數(shù)據(jù)抽象和封裝。數(shù)據(jù)抽象是一種依賴于接口和實(shí)現(xiàn)分離的編...
    小姜愛學(xué)習(xí)閱讀 1,136評論 0 3
  • C++基礎(chǔ)2:類與對象 1. 認(rèn)識類與對象 什么是類(class)?類(class)是類型(type)志衍,是用戶自定...
    jdzhangxin閱讀 2,247評論 0 7
  • 第7章 類 7.1 定義抽象數(shù)據(jù)類型 類的基本思想:數(shù)據(jù)抽象暖庄、封裝。數(shù)據(jù)抽象:一種依賴于接口和實(shí)現(xiàn)分離的編程及設(shè)計(jì)...
    北冥有魚wyh閱讀 300評論 0 1
  • 成員函數(shù)一個名為this的額外隱式參數(shù)來訪問調(diào)用它的那個對象楼肪。當(dāng)我們調(diào)用一個成員函數(shù)時培廓,編譯器負(fù)責(zé)把對象的地址傳遞...
    夢中睡覺的巴子閱讀 173評論 0 0