c 技術文章

2021-04-13 02:54:44 字數 3275 閱讀 9286

看了c++的經典著作《effective c++ 》之後的感想。

大學的時候學校開了c++的課程,我考的還不錯。畢業後就一直搞軟體開發,大概一年前開始用vc做專案。最近靜下心來看了c++的經典著作《effective c++ 》,才發現自己的c++水平其實真的很一般!書中提到的有些東西,我竟然從來沒有注意過!還有些竟然是我第一次聽說!

下面以例項說明(我用我寫的更小的例子代替了書中的例子,書中原文我用紅色標示)。

1.關於類成員的初始化順序問題

條款13的標題是:initialization list中的members初始化次序應該和其在class內的宣告次序相同。

我不知道大家在用c++開發的時候有沒有注意過這個問題,反正我是從來沒有往這方面想過!

下面來看例子:

class

cmyintarray

;private

:std::vector

<

int>

data;

size_t size;

intlbound, hbound;

};cmyintarray::cmyintarray(

intlowbound, 

inthighbound)

: size(highbound 

-lowbound + 1

) , lbound(lowbound)

, hbound(highbound)

, data(size) 

如果沒有看過這本書,沒有任何提示,我想很多搞c++開發的人看不出這簡單幾行**有什麼問題(當然,編譯肯定是不會有問題的)。

可是,如果程式中有類似於下面的**,問題就會在程式執行的時候爆發出來:

cmyintarray otest(5, 

13);

cout 

<<

otest.getarraysize() 

<<

endl;

而且你就算在debug狀態下進行跟蹤也很難發現問題的根源所在!

問題處在什麼地方呢?就在於成員變數的宣告次序上!上面變數宣告的次序改為:

size_t size;

intlbound, hbound;

std::vector

<

int>

data;

問題就可以迎刃而解!

驚奇嗎?為什麼會這樣?書中給出了答案:class members係以它們在class內的宣告次序來初始化;和它們在member initialization list中出現的次序完全無關。

上面**的錯誤根源是:data在初始化的時候size還沒有定義!也就是說要初始化乙個沒有定義大小的vector,當然會出錯。

2.關於「切割問題」

下面是書中的一段話(條款22中):

當乙個derived class object被交出去當作乙個base class object時,它原本所以「成為乙個derived class object」的所有特徵,都會被切除(slicing)掉,只留下內部乙個base class object。

下面是我寫的小例子:

class

cbase;};

class

cderived : 

public

cbase;};

下面是兩個函式:

void

test1(cbase test)

void

test2(

const

cbase

&test)

用下面的**分別呼叫函式test1和test2:

cderived otest;

test1(otest);

test2(otest);

問題是:呼叫函式test1和函式test2分別輸出什麼?

正確答案是:

output from cbase!

output from cderived!

驚奇嗎?一點兒也不驚奇!書中已經給出了為什麼會這樣:以by reference的方式傳遞引數,有另乙個優點:可避免所謂的「切割(slicing)問題」。

3.關於非虛函式的靜態繫結和虛函式的動態繫結

下面是例子:

class

cbase;};

class

cderived : 

public

cbase;};

現在有下面的**呼叫:

cderived  d;

cbase 

*pb =&

d;pb

->

test();

cderived  

*pd =&

d;pd

->

test();

輸出是:

output from cderived!

output from cderived!

output from cbase!

output from cderived!

這時,有些人就會奇怪了,pb和pd指向的都是d,為什麼會這樣輸出呢?

答案就是:非虛函式是靜態繫結的,虛函式是動態繫結的。

書中的條款37給了大家忠告:絕對不要重新定義繼承而來的非虛函式。

4.關於預設值的靜態繫結

還是看例子:

class

cbase

;class

cderived : 

public

cbase;};

下面是呼叫**:

cbase *p 

=new

cderived;

p->

test();

我們的本意是想輸出1,可是結果卻是輸出0!

不用驚奇,書中給出了答案:虛函式系動態繫結(dynamically bound),而預設引數值卻是靜態繫結(statically bound)。

而且,書中的條款38也給了大家忠告:絕對不要重新定義繼承而來的預設引數。

寫在最後:其實vc和bcb之類的只能是c++的開發工具,而基礎還是c++。就算你的vc和bcb用得再熟練,也是僅僅是對其提供的類庫而已,而沒有真正領會c++的精髓。這些是我看了這本書後的感想。現在覺得靜下心來看了這本書,真是受益匪淺呀。希望這篇文章能給讀者一點啟發。我的下乙個目標就是讀c++之父bjarne stroustrup的那本經典著作《the c++ programming language》。如果我有什麼收穫,也會在這裡給大家分享。

Mybatsi技術文章

基礎教程 mybatis學習 之 一 mybatis簡介與配置mybatis spring mysql mybatis學習的乙個系列部落格,非常詳細 mybatis document mybatis官方學習文件 english 中文文件 原理分析 mybatis 快取機制深度解剖 自定義二級快取 l...

技術文章鏈結

基本css樣式.bootstrap bootstrap教程 菜鳥教程 w3cplus 引領web前沿,打造前端精品教程 sharp and clean symbols glyphicons.com 使用超動感html js開發web應用 angularjs中文社群 angularjs 教程 菜鳥教程...

hbase技術文章整理

在學習hbase的過程中,發現了一些比較好的文章,記錄在這裡。1.理論 google bigtable 乙個分布式的結構化資料儲存系統 中文版 bigtable架構 google mapreduce中文版 the google file system中文版 2.基礎 hbase介紹 資料平台與產品部...