看看C 中class裡這些奇怪的東西吧

2021-05-25 17:44:46 字數 4216 閱讀 8392

1 空的class並非不佔空間

它占有乙個位元組的空間,據說這是為了區別物件,編譯器為空類默默的安插進了乙個char到空物件內。既然這樣,那麼我門就來看一下,這個對像能否被繼承到子物件中呢?

code:

#include 

using

namespace std;   

class base   

;   

class derived:public base   

;   

int main()     

輸出結果 1 根據輸出結果,還是輸出了乙個空類的大小,但是若基類中被安插的哪個char能被繼承到派生類中的話,那麼派生類的大小應改為2才對啊。由此可見這個char並不能被繼承或是使用,僅僅是作為乙個區別標誌而已。那麼我們再看一下下面這個程式:

code:

#include 

using

namespace std;   

class base   

;   

class derived:public base   

;   

int main()     

大家可以猜測一下輸出結果。輸出結果為8.也許很出乎你的意料吧。其實這裡編譯器還是吧空物件的大小當成1了。然後在派生類中根據位元組對齊,結果就為8了。

2 類中不佔空間的成員

類中並不是所有的成員都佔空間的。哪那些不占用空間呢?其實當我們知道那些占用空間,剩下的就是不占用空間的了。占用空間的有:非靜態資料成員,虛函式。基本上我就知道這兩個。也就是說靜態資料成員,靜態函式,列舉,非虛函式,typedef這些東西都是不占用空間的。我們帶著這些知識來看乙個程式:

code:

#include

using

namespace std;   

class ds   

;   

private:   

enum e1a;    

};   

int main()     

輸出結果為12 。為什麼為12呢?這裡也許很多同學想不通了。。我們一起來看一下:int 4個位元組,short int 2 個位元組,位元組對齊補充為4個位元組,union不佔空間。為什麼不佔空間呢?union其實也屬於我們上面所說的不佔空間的類成員中的一種。enum不佔空間。那現在才8個位元組啊,為什麼結果是12呢?其實大家仔細看一下就知道了。enum這裡定義了乙個物件a。所以它這裡就占用空間了。若是我們這裡僅僅是enum;它不占用空間。所以問題就出在這個a上。a占用幾個位元組呢?我們都知道enum定義出來的物件本質上就是乙個int型。故它佔4個位元組,這不12了位元組了嗎?

對於上面這個程式,大家可以自己試試,無論你往裡面加多少個非虛函式,多少個靜態成員,多少個類似這樣的enum;列舉和類似 union u1;這樣的聯合體。類物件的大小都不會增加。那麼他們占用的空間在那裡呢?輸出的類物件的大小是屬於記憶體中的那一部分空間呢?這個問題留給大家補充吧,我也不清楚。對於上述說明我們可以看下面程式證明下:

code:

#include

using

namespace std;   

class ds   

;   

//enum e1a; 

static a;   

static b;   

void f(){}   

void g(){}   

};   

int main()   

輸出結果為1.說明此刻編譯器仍把類當做乙個空類來處理。噢,我的天啊。不過這樣的類還真是有用處。我們可以試想一下。我們若是想在乙個類繼承層次裡面。若是乙個基類僅僅是為派生類提供乙個介面,而並提供資料。不就是用的這樣的類嗎?當然我們這裡有靜態成員的資料。我們可以定義乙個僅提供介面的類。stl裡好像就使用了好多這樣的所謂的空類。

3 虛繼承

我們來看一下下面這個程式:

code:

#include

using

namespace std;   

class base   

;   

class derived1:public base   

;   

class derived2:virtual

public base   

;   

int main()   

輸出結果為4,8.大吃一驚吧。呵呵。第乙個結果應該是正常的,我想大家對這個不會有異議。因為derived1繼承了基類的虛函式。虛函式是佔4個位元組的。故結果為4.那第二個為什麼是8呢。也不應該是4嗎?其實這時編譯器好像是往虛函式表裡又增加了乙個指標。具體也不是很清楚,求知中。。

4 我們可以為純虛函式定義

這點我以前確實不知道。今天才在書上看到。原來我們也可以為純虛函式定義,我們看下面這個程式:

code:

#include

using

namespace std;   

class base   

;   

void base::f()   

class derived1:public base   

};   

class derived2:virtual

public base   

};   

int main()     

我們為基類的純虛函式做了定義。然後我們又在兩個派生類進行了重定義,並在定義體裡呼叫了基類的虛函式。呵呵。。具體結果是什麼自己試試吧。但是若我們不在派生類中進行重定義的話,派生類也會被編譯器預設為虛類的。即無法進行例項化。對於這樣的用法又有什麼用呢?我們可以設想這樣一種情況,即我們不想讓客戶對我們的基類進行例項化,而我們又像我們的客戶在派生類中重定義自己的函式時引用我們基類中的函式部分。這樣若是我們將我們的基類中的函式定義為虛函式的話,可以試現我們的後一部分,但可以還是可以例項化,這樣我們就可以用我們這個方法,使用者不可以進行例項化了,又可以通過呼叫基類的哪個我們定義過的純虛函式來引用基類部分。

5 析構函式也可以被繼承?

我們都知道我們若是若是準備讓乙個類作為基類來用的話,一般都會吧它的析構函式定義為虛函式的。為的是多型性,即讓我們用乙個基類的指標指向乙個派生類物件時。我們用delete刪除這個基類指標時,可以動態的呼叫派生類的析構函式來析構派生類部分。否則就會產生記憶體洩露。我們來看下面這個程式:

code:

#include

using

namespace std;   

class base   

};   

class derived:public base   

;   

int main()     

結果僅僅呼叫了基類的析構函式,具體派生類的析構函式是否呼叫了。我們無法看出來。若我們重定義一下,那肯定就呼叫了。。呵呵。但是在這種情況下到底呼叫了嗎?乙個謎底。只有寫編譯器,定義c++標準的人才能告訴我們正確的答案,因為規則使他們定的。但我們根據我們對c++的學習也是可以猜出答案的。

可是我們仔細分析一下你估計就會迷惑了!現在derived物件的大小為多少。1對吧。也就是編譯器為我們安插進去的那個char。這個char是屬於base還是derived的呢?不得而知。。暫且不管他吧。。我們看一下析構函式,析構函式是用來幹什麼的?釋放空間。對吧。現在我們的base指標t目前僅僅有乙個位元組的空間,而我們這裡卻呼叫了兩次析構函式,這又怎麼解釋。乙個位元組的空間需要兩次釋放?不不。我們換個方式思考,我們看下面這個程式:

code:

#include

using

namespace std;   

class base   

};   

class derived:public base   

};   

int main()     

這個程式中明確輸出了派生類有乙個位元組的空間。然而當我們的程式結束時卻呼叫了兩次析構函式。我們都知道當我們乙個派生類物件的生命期結束時會呼叫派生類的析構函式析構派生類部分,然後呼叫基類的構造函式呼叫基類部分。然而我們這個派生類中僅有乙個位元組的空間啊。到底它是怎麼析構的呢。迷。。迷。。。。

我們再看一下我們這個題目,析構函式也可以被繼承?為什麼這麼問呢?它確實會令人產生聯想。設想多型行為。是有乙個基類物件的指標或引用指向派生類物件,然後呼叫虛函式產生的。被稱為執行期行為,即只有到執行期才能確定掉用的具體物件。然而我們的析構函式的多型行為,和這個很是類似。這又是怎麼回事?我們的析構函式該是不能被繼承啊。。畢竟他在每個類中的名字都不一樣。然而這樣的多型行為是怎麼產生的?僅僅是乙個規則,還是有章可循的?。。

c 中class 中的this指標

1.this指標的經典描述 當你進入乙個房子後,你可以看見桌子 椅子 地板等,但是房子你是看不到全貌了。對於乙個類的例項來說,你可以看到它的成員函式 成員變數,但是例項本身呢?this是乙個指標,它時時刻刻指向你這個例項本身 2.this指標的使用 一種情況就是,在類的非靜態成員函式中返回類物件本身...

C 中struct和class的差別

在c 中,struct和class除了預設訪問控制級別不一樣,其它別無二致,具體怎麼用,純屬於個人習慣。另 在stroustrup c 發明者 的原作中 他自己說的原句是 按照定義,乙個struct就是乙個類,而只是完全公開的類 所以 struct s 等價於class s public 也就是說,...

C 中class與struct的區別

類與結構的例項比較 類與結構的差別 如何選擇結構還是類 一 類與結構的示例比較 結構示例 類示例 呼叫過程 從上面的例子中我們可以看到,類的宣告和結構的宣告非常類似,只是限定符後面是 struct 還是 class 的區別,而且使用時,定義新的結構和定義新的類的方法也非常類似。那麼類和結構的具體區別...