討論記錄之C 細節

2021-08-29 16:55:16 字數 3646 閱讀 8003

participants:lf,hzp,cpp,zy

date:08-09-16

7:20pm

recorder: cpp,zy

參考文獻:

1、《effective c++》2nd edition,scott meyers etc.

2、《c++程式設計教程》,錢能

3、《高質量c++c程式設計指南》,林銳

4、應大家的要求,今天晚上開始了我們的第一次討論會。

主要是針對c++裡面的一小撮問題展開的,這裡我給出討論的概要:

1、關於優先順序與結合性;(這裡要重點「批」一下hzp和zy,正號和加號都分不清的傢伙…)(頂)

2、#define \inline\const(順便涉及到inline 和virtual的連用問題);

3、const的作用(包括修飾類的成員函式,成員函式返回值,成員函式的引數列表,資料成員);

4、過載、覆蓋(重寫/改寫,實現多型)以及隱藏的區別;

5、建構函式和析構函式

6、關於虛函式、虛基類及多繼承

1、優先順序口訣:(除了標明是右結合外,都是左結合)

括號成員第一;//、()

全體單目第二;//比如++、--、+(正號)、-(負號)、指標運算子* & 右結合

乘除餘第三;//取餘左結合

移位五,關係六;

等於不等排第七;

位與亦或和位或;//&、^、|

邏輯或跟與;//&&、||

條件高於賦值;//注意的是賦值運算子很多,包括= 、*=、/=、+=、-= 、|=、<<=>=  二者都是右結合

逗號排最後。

上面是c中的規則,而c++由於引入了一些新的運算子,因此,有些出入,如表1:

表1 c

++ 運算子優先順序列表

見兩個例子:

(1) int x=1,y=0;

!x&&x+y&&++y;

加括號確定優先順序的方法

當多個優先順序不同的運算子在一起時,為了不混淆,可以先加上括號,這樣就分出層次了,相同層次的考慮結合性問題,當確定下來先算那塊時,再往這塊裡面深入。例如上面的例子,我們可以這樣加上括號:從左向右看,由於!比&&優先順序高,所以有(!x),又由於&&比+優先順序低,所以有(x+y),而++優先順序高於&&,所以(++y)。這樣整個式子就變成了:(!x)&&(x+y)&&(++y),最外層的是兩個&&運算,由於&&的結合性是從左至右,所以上式可看成:a&&b&&c,先計算a,再計算b,最後算c.由於x=1,則!x就為假,後面的就不需要再算了,整個語句的值為假。執行完後,y的值沒變,還是0.

所以碰到不清楚先算誰後算誰時,先加個括號看看,就明白了先後次序。

(2)給語句c=a>b?a:b;加括號。此語句有三個運算子:=、>、?:,應該怎樣加括號呢?

第一種方案:c=((a>b)?a:b);

第二種方案:c=(a>(b?a:b));

第三種方案:(c=a)>(b?a:b);

應該是那一種呢?按照運算子優先順序的高低順序,>優先順序高於=,所以不可能把(c=a)括起來。優先順序高於?:運算子。所以也不可能把(b?a:b)括起來。因此,第一種答案正確。

2、盡量以constinline取代#define

盡量以編譯器取代預處理器或許更好,因為#define通常不被視為語言本身的一部分。

#define導致的結果就是程式內所使用的名稱並未出現於符號表之中。可以改用常量來宣告。

若是需要乙個class專屬常量,即將這個常量的scope侷限於class 之內,必須讓它成為乙個member,而為了確保這個常量至多只有乙份實體,則必須讓他成為乙個static member,例如:

class gameplayer;

必須在類定義檔案中定義該類成員:const int gameplayer::num=5;

另乙個誤用#define指令的常見例子是,以它來實現巨集——看起來像函式,卻又不會帶來函式呼叫所需的成本。經典例子就是計算兩數的最大值:

#define  max(a,b)  ((a)>(b)?(a) : (b))

即使加上了小括號,還是會發生乙個可怕的動作:

int a=5,b=0;

max(++a,b);//a被累加兩次

max(++a,b+10);//a被累加一次

這時,我們可以使用inline函式,既可以得到巨集帶來的高效率以及函式帶來的可預期行為和型別檢驗。例如:

inline int max(int a, int b)

這與前述巨集並不完全相同,因為這個版本的max只接受int型別引數,不過,template可以修正這一問題,這裡by reference相比by value可以獲取更高的效率。

template

inline const t& max(const t& a, const t&b)

3const的作用

(1)修飾類的成員函式時:

即在成員函式宣告時將const置於成員函式引數列表後分號前,代表它不能對類的資料成員進行修改,但是有乙個例外,就是當資料成員前有mutable修飾時,它是可以被該函式修改的;

(2)修飾成員函式返回值及函式引數時:

意即被修飾的量是不可被修改的,前者意味著在成員函式返回後得到的值不可被更改,後者意味著不能在函式體內對引數進行變動,只能讀取它;

(3)對於類中的const常量,它只在某個物件生存期內是常量,而對於整個類而言卻是可變的,因為類可以建立多個物件,不同的物件其const資料成員的值可以不同。

不能在類宣告中初始化const資料成員,只能在類建構函式的初始化表中進行,例如:

class a ;

應該是:

class a ;

a::a(int size):size(size)

若要建立在整個類中都恆定的常量,需要用列舉常量來實現,例如:

class a;//

int array1[size1];

int array2[size2]; };

列舉常量不會占用物件的儲存空間,它們在編譯時被全部求值。列舉常量的缺點是:它的隱含資料型別是整數,其最大值有限,且不能表示浮點數.(pi=3.14159)

4、過載(overload)、覆蓋(override)以及隱藏

本來是討論多型的,但是我們又講到了過載這個概念,對於乙個類中的成員函式,其被過載的特徵:

(1)相同的範圍(同乙個類中);

(2)函式名相同,引數列表不同,返回值型別可相同也可不同。

覆蓋是指派生類函式覆蓋基類函式,其特徵:

(1)不同範圍;

(2)函式名字相同,引數列表相同,

(3)基類必須要有virtual關鍵字。

除覆蓋外,所有同名的基類函式與子類函式都屬於隱藏,下面是乙個例子,講得比較清楚,也點出了問題的本質:

class base  

void g(float x)

void h(float x)

};派生類:

class derived:public base

{public

請先不要討論細節好嗎

場景一 專案經理接到乙個新的專案,把大家叫到一起開會來介紹這個新的專案。首先,他介紹了這個專案是幹什麼用的。然後開始了下面的介紹。大家看,這個地方使用者需要輸入乙個訂單,這個訂單呢,就是這麼乙個表 說著畫出了標的結構 這個欄位呢可能有些問題。下面有乙個人馬上就說了 可是我覺得叫這個名字怎麼這麼奇怪呢...

python 細節記錄

1 在jupyter notebook 中執行 沒有執行結果,只是出現 int 標識 1 restart 2 pip install notebook 也許是沒有安裝notebook導致的。2 python 錯誤 syntaxerror invalid character in identifier...

穩定的完成埠開發細節討論

完成埠做為windows上最高效的網路程式設計模型,做為眾多伺服器網路層的首選。網上有很多參考資料和示例原始碼,大多存在問題,本文將以開發乙個穩定易用的完成埠元件為目標,詳細討論開發過程中所遇到的細節問題,並給出相應的解決方案。閱讀本文需要你有這方面的開發經驗,對於iocp的工作流程以及上層的應用有...