C++程序設(shè)計(jì)一些深層次的細(xì)節(jié)

本文預(yù)覽:

  • 轉(zhuǎn)換函數(shù) 與 non-explict-one-argument Ctor
  • pointer-like class
  • function-like class
  • Reference經(jīng)驗(yàn)談

前言

本篇會(huì)提到一些瑣碎的東西,雖然有一些在我們編寫代碼的過(guò)程中不經(jīng)常用到,但是都是一些幫助你理解C++底層次的東西。網(wǎng)上有人開(kāi)玩笑說(shuō),一個(gè)java程序員學(xué)了三年,師傅對(duì)他說(shuō),你已經(jīng)精通java了,可以下山了;一個(gè)C++程序員,學(xué)了十年,師傅對(duì)他說(shuō),你可以下山了,但是不要說(shuō)你精通C++。這當(dāng)然只是個(gè)笑話,但是從側(cè)面反映出一個(gè)深刻的道理,那就是C++坑大水深,入坑需謹(jǐn)慎~。既然你已經(jīng)入坑了,不想就此自費(fèi)武功,那就好好修煉內(nèi)功吧。

轉(zhuǎn)換函數(shù) 與 non-explict-one-argument Ctor

轉(zhuǎn)換函數(shù)是什么鬼?類型轉(zhuǎn)換嘛,顧名思義。轉(zhuǎn)換函數(shù)記住一句話就好了,有轉(zhuǎn)出去和轉(zhuǎn)進(jìn)來(lái)之分。
舉個(gè)例子:設(shè)計(jì)一個(gè)分?jǐn)?shù)類 x/y

class Fraction {//這個(gè)分?jǐn)?shù)類還是非常簡(jiǎn)單的嘛
public:
    Fraction(int x, int y = 1):_x(x),_y(y){}
    inline int x() const {return _x;}
    inline int y() const {return _y;}
    operator double() const
    {
        return (double)(_x ) / (double)(_y);
    }
    Fraction operator+(const Fraction& f)
    {
        return Fraction(...);
    }
private:
    int _x; //分子
    int _y; //分母
};

分?jǐn)?shù)類設(shè)計(jì)好了,使用的時(shí)候出現(xiàn)問(wèn)題了:

Fraction f(3,5);
double d = 4 + f;

一個(gè)整數(shù)加一個(gè)分?jǐn)?shù),能編譯通過(guò)嗎?我們是不是還需要重載一個(gè)+操作符來(lái)來(lái)實(shí)現(xiàn)運(yùn)算呢?現(xiàn)在好像是不用了,編譯器能通過(guò)編譯,計(jì)算結(jié)果也是正確的。你也許已經(jīng)注意到了:

    operator double() const
    {
        return (double)(_x ) / (double)(_y);
    }

這就是轉(zhuǎn)換函數(shù)的語(yǔ)法,沒(méi)有返回值類型,函數(shù)名稱就已經(jīng)說(shuō)明了你需要轉(zhuǎn)換出去的類型。C++編譯器會(huì)這么在遇到 4+f的時(shí)候首先會(huì)去尋找operator+(int),都沒(méi)有int可以穩(wěn)定轉(zhuǎn)成double, operator+(double)肯定是有的,double+double類型能通過(guò)嗎?找找看Fraction能轉(zhuǎn)成double類型嗎?operator double(),定義了轉(zhuǎn)換到double類型的函數(shù),可以轉(zhuǎn)換。

現(xiàn)在我們把轉(zhuǎn)換函數(shù)去掉,F(xiàn)raction不能轉(zhuǎn)成double了:

Fraction f(3,5);
double d = f + 4;

我們也沒(méi)有operator+(const double) ,但是編譯能過(guò)嗎?我們重載了一個(gè)operator+(const Fraction&),這個(gè)必須是要有的,沒(méi)有重載+肯定是編譯不過(guò)的,也就是說(shuō),我們這次的+,肯定是用到了operator+(const Fraction),那么好了,如果能編譯通過(guò),肯定是int轉(zhuǎn)成了Fraction類型了。但是,我們不可能去修改C++語(yǔ)言內(nèi)核,在int里也加一個(gè)轉(zhuǎn)換函數(shù)吧。為題出在哪里了?它怎么自動(dòng)轉(zhuǎn)的,這就用到了non-explict-one-argument Ctor, 自動(dòng)調(diào)用了Fraction的構(gòu)造函數(shù),把int轉(zhuǎn)換成了Fraction。

注意:

Fraction(int x, int y = 1):_x(x),_y(y){}
// explict Fraction(int x, int y = 1):_x(x),_y(y){}

這種構(gòu)造函數(shù)叫做non-explict-one-argument Ctor,前面沒(méi)有explict修飾,并且只有一個(gè)實(shí)參,第二個(gè)參數(shù)是有默認(rèn)值的,如果沒(méi)有默認(rèn)值就不能叫one-argument。如果沒(méi)有加explict編譯器是可以自行調(diào)用,把其他類型轉(zhuǎn)進(jìn)來(lái)的。加了explict,編譯就不通過(guò)了。

pointer-like class

pointer-like class:把class設(shè)計(jì)出來(lái)當(dāng)做指針用。在智能指針和迭代器都是這么設(shè)計(jì)的。

  1. 智能指針的設(shè)計(jì)
智能指針的設(shè)計(jì)

智能指針被C++設(shè)計(jì)用來(lái)管內(nèi)存,寫法相當(dāng)固定,必須要重載的和->,解引用這個(gè)應(yīng)該都是沒(méi)有什么困惑,但是問(wèn)題在->這個(gè)問(wèn)題就出來(lái)了,sp->method()調(diào)用返回的是T啊,在第一次已經(jīng)使用了->,返回的T*還怎么調(diào)用method(),C++語(yǔ)法定義了->有繼續(xù)作用的特性。這個(gè)問(wèn)題就解決了。我們第一次雖然使用了->,但是由于C++語(yǔ)法規(guī)定,->能繼續(xù)作用,因此,智能指針這么設(shè)計(jì)是沒(méi)有問(wèn)題的。

  1. 迭代器的設(shè)計(jì)

迭代器在STL里大部分都被設(shè)計(jì)成了class,迭代器的使用方法也很像是指針,我們以list的迭代器來(lái)看,是如何重載指針的解引用和調(diào)用操作符的。

迭代器的設(shè)計(jì)

在list中*操作符將獲取元素對(duì)象,也就是list_no
![Uploading 屏幕快照 2017-03-08 16.00.50_078916.png . . .]
de<T>的data部分;->操作符獲得data的指針。這樣,我們就能使用迭代器,直接獲取list元素對(duì)象和調(diào)用相應(yīng)的方法了。

function-like class 所謂仿函數(shù)

function-like class: 將類設(shè)計(jì)出來(lái),當(dāng)做函數(shù)使用,又叫仿函數(shù)。其實(shí)質(zhì)就是在里面重載了()操作符

仿函數(shù)在STL中

STL里面的算法less實(shí)現(xiàn):

template <class T>
struct less
{
     bool operator()(const T& x, const T& y) const {return x < y; }
}

這是算法嗎?分明就是一個(gè)class,這是一個(gè)class嗎?這不是仿函數(shù)嗎?自己好像很少用到仿函數(shù)吧,C++11里面出現(xiàn)了lamda表達(dá)式之后對(duì)仿函數(shù)簡(jiǎn)直就是秒殺有沒(méi)有。但是它確實(shí)在STL里面有大量的應(yīng)用。

    bool ret = less<int>()(2,1);        //第一個(gè)()表示是一個(gè)臨時(shí)對(duì)象,第二個(gè)()才真正調(diào)用了operator()
    cout<<ret<<endl;
    
    float d = plus<float>()(1.2,2.1);
    cout<<d<<endl;

以上是使用示例。

Reference經(jīng)驗(yàn)談

如果從內(nèi)存角度看一個(gè)變量,那么變量大概可以分為三類:

  • value : 分配一塊內(nèi)存空間放值
  • pointer : 分配一塊內(nèi)存空間放地址
  • reference : 分配一塊地址空間,放一個(gè)對(duì)象,這個(gè)對(duì)象代表了他所引用的對(duì)象
int x = 0;
int& r = x;
cout<<x<<endl;
cout<<&x<<endl;
cout<<sizeof(x)<<endl;

cout<<r<<endl;
cout<<&r<<endl;
cout<<sizeof(r)<<endl;

你所看到的r和x所有的都是一樣的,于是我們稱reference是object的別名。但是它的內(nèi)部實(shí)現(xiàn)是指針,但是它屏蔽了指針的概念和用法,在用法上和它所引用的對(duì)象是一樣的。

關(guān)于引用需要知道:

  1. 一個(gè)引用變量在創(chuàng)建的時(shí)候要有初始值;
  2. 通常不用做變量聲明,而作為參數(shù)傳遞;
  3. java里面的所有變量都是reference;
  4. 修改引用,也會(huì)修改它所代表的對(duì)象;
  5. 實(shí)現(xiàn)是指針,邏輯上我們理解為代表或者別名。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,698評(píng)論 6 539
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,202評(píng)論 3 426
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 177,742評(píng)論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 63,580評(píng)論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,297評(píng)論 6 410
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 55,688評(píng)論 1 327
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,693評(píng)論 3 444
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 42,875評(píng)論 0 289
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,438評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,183評(píng)論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,384評(píng)論 1 372
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,931評(píng)論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,612評(píng)論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 35,022評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 36,297評(píng)論 1 292
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,093評(píng)論 3 397
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,330評(píng)論 2 377

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