C 語法小結 2

2021-08-30 14:54:21 字數 2812 閱讀 1844

7. 虛函式在繼承層次的作用域

「如果通過基類的引用或者指標呼叫虛函式成員,那麼編譯器將在基類中查詢函式名。假定找到了函式名,編譯器就檢查實參與形參是否匹配。這也是虛函式必須在基類和派生類中擁有同一原型的原因。」

如果在派生類中定義了與基類虛函式同名但函式原型不同的函式,那麼該函式將遮蔽基類定義的虛函式。

總之,(1)無論呼叫虛函式還是非虛函式,都是在編譯時期根據呼叫者的靜態型別來進行名字查詢與函式型別檢查。

(2)派生類的作用域巢狀在基類的作用域中,派生類可以重寫(覆蓋)基類定義的虛函式,也可以遮蔽基類的虛函式或者非虛函式。

如下示例:

class cls1_t

};class cls2_t: public cls1_t

};int main()

8. 多繼承

「在多重繼承下,派生類的指標或引用可以轉換為其任意基類的指標或者引用」。如下:

struct cls11_t;

struct cls22_t: virtual public cls11_t;

struct cls31_t: public cls21_t, public cls22_t{};

void fcn1(cls11_t &obj)

void fcn2(cls21_t &obj)

void fcn3(cls22_t &obj)

int main()

程式將輸出:

i'm in cls11_t

i'm in cls21_t

i'm in cls22_t

9. 當實參為陣列型別時,函式模板形參形式對其型別的影響

9.1 實參為陣列型別時,普通函式形參形式對其型別的影響

陣列型別為const 指標,且附帶元素的型別和陣列長度資訊,僅當陣列元素的型別和陣列長度均相同時,兩個陣列型別才相同。比如,有「int a[16], b[15]」,a,b不是同乙個型別,因為陣列的長度不同。

當實參為陣列型別時,比如有「int a[16];」,以a 作為實參,如果形參是非引用型別,比如「int pa[n]」,n為值任意的常量表示式,那麼編譯器將pa 處理為int * 型別,而不是陣列型別int [n]。如果形參是引用型別,比如「int (&pa)[n]」,那麼編譯器將pa 處理為陣列型別:int [n],這時編譯器會檢查實參與形參型別是否匹配,即這兩個陣列型別的元素型別陣列長度必須相同,否則實參與形參型別不匹配導致編譯出錯。

示例如下:

void fcn1_1(int (&a)[16])

void fcn1_2(int (&a)[15])

void fcn1_3(int (&a)[17])

void fcn2_1(int a[16])

void fcn2_2(int a[15])

void fcn2_3(int a[17])

int main()

9.2 實參為陣列型別時,函式模板形參形式對其型別的影響

與普通函式類似,當函式模板中函式形參為引用型別時,編譯器將形參作為陣列型別處理(陣列型別附帶陣列元素型別和陣列長度資訊),當

template

void printary(const t &ary)

template

void printary2(const t ary)

template

void printary3(const t (&ary)[n])

template

void printary4(const t ary[10])

template

void printary5(const t ary[n])

int main()

程式輸出:

sizeof(ary)=32

sizeof(ary)=4

sizeof(ary)=32, n=8

sizeof(ary)=4

printary(),printary4()與普通函式的情形類似,形參為引用型別,則被處理為陣列型別,否則,被處理為指標型別。printary2()實際上也與普通函式情類似,此時t實參型別為int *,而在printary4()

中,t的實參型別為int。printary3()實際上也與普通函式的情形類似,此時t的實參型別為int,而printary()中t的實參型別為int[8]。printary5()是錯誤的,因為ary為非引用型別,被編譯器當做指標型別處理,指標型別是不附帶陣列長度資訊的,因此,編譯器無法計算出n值。

在實參為陣列型別的情況下,在函式模板中,仍就遵循引用型別的形參為陣列型別,非引用型別的形參為指標型別,只是模板的型別形參可能不同,因此模式比普通函式的情況多一些。

10. dynamic_cast 相關

dynamic_cast(base_t *pobj):用於在執行時檢查基類指標pobj所指的物件,如果該物件為derived_t型別,則將其位址轉換為derived_t *型別。但是,如果像以下那樣呼叫dynamic_cast,那麼dynamic_cast總會呼叫成功,

dynamic_cast< base_t *>(base_t *pobj),不論在執行過程中pobj指向的是base_t型別的物件,還是其派生類的物件,dynamic_cast總能成功呼叫,所以這樣呼叫並沒有意義。示例如下:

struct base_t

};struct derived_t: base_t

};int main()

執行結果為:

base_t: same type

derived_t: different type

可以將base_t::sametype()的if子句改為:if (typeid(obj) == typeid(base_t)),以區分基類物件和派生類物件的型別。

C 陣列小結(2)

二 二維陣列 對於乙個n維陣列,其實質上還是乙個一維陣列,這個一維陣列的每個元素又都是乙個 n 1 維陣列。以此類推。複雜的不去深究,就看二維陣列a m n 實質是乙個由m個元素組成的一維陣列,每個元素又都是含n個元素的一維陣列,這個二維陣列共計m n個元素。對於乙個二維陣列,它實質上是乙個一維陣列...

shell語法小結

原帖 http blog.chinaunix.net u1 34739 showart 283263.html 1 set命令 當沒有引數的時候,列出系統中所有的自定義變數值 當有引數的時候,重置基本引數如 1 2等。如 set date 將date 命令的輸出當作輸入引數 2 let命令 執行算術...

lua語法小結

學習lua程式設計的必備資料是 如果是學習語言本身,那麼可以看 1.注釋 lua用兩個減號 注釋的開始,如 這個句子被注釋 還有另一種方法來注釋多行 第一行被注釋 第二行被注釋 2.型別 lua是弱型別的.lua裡有一種型別是nil,它代表什麼都沒有.未被賦值的變數都等於nil.3.運算子 lua的...