C++之struct构造函数(2010-10-19 15:04:47)
C++之struct構(gòu)造函數(shù)
(2010-10-19 15:04:47) 轉(zhuǎn)載 標(biāo)簽: cppstruct構(gòu)造函數(shù)校園 | 分類: C/C_PlusPlus |
??? ?在網(wǎng)絡(luò)協(xié)議、通信控制、嵌入式系統(tǒng)的C/C++編程中,我們經(jīng)常要傳送的不是簡單的字節(jié)流(char型數(shù)組),而是多種數(shù)據(jù)組合起來的一個整體,其表現(xiàn)形式是一個結(jié)構(gòu)體。
???? 下面看看一道關(guān)于C++中筆試題:
// FileName:test.cpp
1:??#include <stdio.h>
2:? struct test
3:? {
4:?????? test(int n){
5:?????????? printf("test(%d)/n",n);
6:?????? }
7:?????? test(){
8:?????????? printf("test()/n");
9:???????? }
10:????? void Fun(){
11:????????? printf("Fun()/n");
12:????? }
13:? };
14:? int main()
15:? {
16:????? test a(1);
17:????? a.Fun();
18:????? test b();
19:????? b.Fun();
20:????? return 0;
21:?? }
??? 找出這個程序錯誤的一行?
??? 答案很簡單就是第19行,往下看就知道為什么啦!
??? 結(jié)構(gòu)是一種用關(guān)鍵字struct聲明的自定義數(shù)據(jù)類型。與類相似,也可以包含構(gòu)造函數(shù),常數(shù),字段,方法,屬性,索引器,運算符和嵌套類型等,不過,結(jié)構(gòu)是值類型。但是,C++的結(jié)構(gòu)和類是有區(qū)別的:
1、結(jié)構(gòu)的構(gòu)造函數(shù)和類的構(gòu)造函數(shù)不同。
?? a.結(jié)構(gòu)不能包含顯式的無參數(shù)構(gòu)造函數(shù)。結(jié)構(gòu)成員講自動初始化為它們的默認(rèn)值。
?? b.結(jié)構(gòu)不能包含以下形式的初始值設(shè)定類:base(argument-list);
2、對于結(jié)構(gòu)中的實例字段成員,不能在聲明時賦值初始化。
3、聲明了結(jié)構(gòu)類型后,可以使用new運算符創(chuàng)建構(gòu)造對象,也可以不使用new,如果不使用new,那么在初始化所有字段之前,字段將保持未賦值狀態(tài)且對象不可用。
4、結(jié)構(gòu)不支持繼承,即一個結(jié)構(gòu)不能從另一個結(jié)構(gòu)或類繼承,而且不能作為一個類的基類。但是,結(jié)構(gòu)從基類OBJECT繼承。結(jié)構(gòu)也可以實現(xiàn)接口。
??? 從編譯角度來思考下:
摘自csdn: http://blog.csdn.net/fuadam/archive/2008/08/04/2766616.aspx
??? 最近才知道struct和class的靜態(tài)構(gòu)造函數(shù)的觸發(fā)規(guī)則是不同的,不像class在第一次使用類的時候觸發(fā)靜態(tài)構(gòu)造函數(shù)。如果只訪問struct實例的字段是不會觸發(fā)靜態(tài)構(gòu)造函數(shù)調(diào)用的。通過測試發(fā)現(xiàn)當(dāng)訪問靜態(tài)字段,struct本身的函數(shù)(靜態(tài)和實例)和帶參數(shù)的構(gòu)造函數(shù)就會引起靜態(tài)構(gòu)造函數(shù)的執(zhí)行。而調(diào)用默認(rèn)構(gòu)造和未覆寫的基類虛函數(shù)是不會的。為什么呢?
??? 讓我們先來看看class和struct在調(diào)用構(gòu)造函數(shù)時的區(qū)別。class使用newobj指令而struct使用initobj指令來構(gòu)造對象。newobj在堆上申請一塊內(nèi)存并調(diào)用相應(yīng)的構(gòu)造函數(shù)進(jìn)行初始化,然后將對象地址返回給計算棧。initobj則是從本地變量表中載入已經(jīng)分配出來的struct實例然后初始化struct的各字段。這個初始化過程是CLR內(nèi)部執(zhí)行的,而不像class編譯器會給class添加一個默認(rèn)構(gòu)造函數(shù)(這就是為什么struct不能給字段添加默認(rèn)值的原因。但在類中如果給字段添加了默認(rèn)值編譯器就會自動在構(gòu)造函數(shù)中添加字段賦值操作)。如果給struct中定義了一個有參數(shù)的構(gòu)造函數(shù),那么系統(tǒng)就不會使用initobj指令,而是直接用call指令調(diào)用帶參數(shù)的構(gòu)造函數(shù)。
??? 我們最常見最常用的調(diào)用函數(shù)的指令是call和callvirt。對于靜態(tài)函數(shù)使用call指令,對于class使用callvirt指令(不論class中的函數(shù)是不是虛的)。只有子類調(diào)用父類的函數(shù)的時候(避免遞歸調(diào)用)以及構(gòu)造函數(shù)中(由編譯器添加保證父類字段被初始化)使用call指令。而對于struct我們發(fā)現(xiàn)只要調(diào)用的函數(shù)是struct本身定義的都是使用call指令。call和callvirt指令的差別在于,call會把調(diào)用的函數(shù)當(dāng)作靜態(tài)函數(shù)看待,而不會關(guān)心調(diào)用當(dāng)前函數(shù)時實例指針(this)是否為空。這就是struct調(diào)用函數(shù)時為什么都是call因為struct實例是不可能被置為null的。實際上class在調(diào)用非虛函數(shù)時實際上也是使用call的只是多做了一步驗證——this是否為空,讓我們來驗證一下。
總結(jié)
以上是生活随笔為你收集整理的C++之struct构造函数(2010-10-19 15:04:47)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: DELPHI 通過窗口句柄或窗口标题得到
- 下一篇: 作者:杨琪,数据堂(北京)科技股份有限公