結(jié)果是輸出A籽慢。
Google一通得出的結(jié)論是:初始化為NULL的類指針可以安全調(diào)用不涉及類成員變量的類成員函數(shù)而不出錯,但是如果類成員函數(shù)中調(diào)用了類成員變量則會出錯猫胁,既然賦值為NULL的情況都可以使用箱亿,那么自然不初始化的類指針同樣滿足這類情況。
假設(shè)現(xiàn)在有一個簡單的類定義如下:
class Test
{
public:
void func(){cout << "hahaha" << endl;}
int get(){return a+b;}
Test():a(1),b(2){}
public:
int a,b;
};
而之后編譯器會自動將這個類轉(zhuǎn)換成:
class Test
{
int a,b;
};
void _test_func(Test * this);
int _test_get(Test* this);
........
類中的函數(shù)被編譯器靜態(tài)編譯了弃秆,所有非虛函數(shù)(虛函數(shù)呢届惋?別急,待會會解釋到)都可以調(diào)用菠赚,因為函數(shù)地址在編譯期間已經(jīng)確定脑豹。我們知道,類中的成員函數(shù)都是通過this指針調(diào)用成員變量的衡查,編譯器會將this指針作為默認(rèn)參數(shù)傳給類成員函數(shù)的瘩欺,如myclass.function(int a,int b) --> function(&myclass,int a,int b)
好,現(xiàn)在我們添加main函數(shù)如下:
int main()
{
Test *p=NULL;
p->func();//正確,沒有調(diào)用成員變量俱饿,沒有使用空的this指針
p->get();//錯誤歌粥,this指針為空,通過this指針調(diào)用變量所以出錯
return 0;
}
運(yùn)行結(jié)果見上面注釋拍埠,沒有調(diào)用成員變量的func()函數(shù)正確執(zhí)行阁吝,調(diào)用了成員變量的get()函數(shù)錯誤。兩者其實都傳入了空的this指針械拍,前者沒出錯僅僅是因為沒有調(diào)用this指針,而后者調(diào)用了装盯。調(diào)用成員函數(shù)的時候坷虑,函數(shù)地址是編譯期間確定的,成員函數(shù)不通過對象指針(也即當(dāng)前的p指針)去調(diào)用埂奈,對象指針僅僅作為參數(shù)傳入函數(shù)然后去調(diào)用成員變量迄损。
總結(jié)一下:
成員函數(shù)在靜態(tài)編譯的時候地址已經(jīng)確定辞嗡,調(diào)用的時候直接通過函數(shù)地址調(diào)用捆等,this指針只是參數(shù)傳入,p->get()也一樣续室,只不過其內(nèi)部調(diào)用了空的this指針來調(diào)用成員變量栋烤,所以出錯。
再補(bǔ)充一個知識點:
類在實例化對象后挺狰,對象占內(nèi)存的大小明郭,是取決于類里的非靜態(tài)數(shù)據(jù)成員
。類的 靜態(tài)數(shù)據(jù)成員
她渴,非靜態(tài)成員函數(shù)
达址, 靜態(tài)成員函數(shù)
,都不會影響對象所占內(nèi)存空間的大小趁耗。
這是為啥呢沉唠?
就像我們剛剛看到,因為靜態(tài)數(shù)據(jù)成員是屬于整個類的苛败,為該類的每個對象所共有的满葛,每個對象用到的靜態(tài)成員變量径簿,其實同一個東西;
而非靜態(tài)成員函數(shù)呢嘀韧?其實也是屬于類的篇亭,每個該類的對象,調(diào)用的非靜態(tài)成員函數(shù)锄贷,其實也都是同一個的译蒂,那為啥同一類的不同對象調(diào)用某一個非靜態(tài)成員函數(shù)會得到不同的結(jié)果呢?因為this指針哈谊却!this指針使得不同對象調(diào)用同一個函數(shù)柔昼,也可以得到不一樣的結(jié)果。