C++類對象和類指針 剖析

有下面的一個CPerson類:

class CPerson
{
public:
    void show()
    {
        cout<<"I am a people"<<endl;
    }
};

在實際編程中,我們經(jīng)常會看到一個類型有下面兩種不同的使用方式:

CPerson s1;
CPerson *s2 = NULL;
s2 = new CPerson();
s1.show();
s2->show();
delete s2;

那么這兩者在實際的使用中到底有何差別呢,下面從不同的方面來剖析一下。

調(diào)用方式上的不同

首先二者最明顯的區(qū)別就是調(diào)用方式上的不同,對象使用" . "操作符調(diào)用,而指針使用" -> "操作符調(diào)用,且指針在調(diào)用時需要先用new來分配空間,且用完后必須手動delete掉。如不想手動delete也可使用智能指針。

內(nèi)存空間上的不同

二者的類型決定了它們在內(nèi)存上的分布不同,一個是對象類型,一個是指針類型。對象類型在創(chuàng)建時就已為對象分配好內(nèi)存空間,用的是內(nèi)存棧,是個局部的臨時變量,作用域在該函數(shù)體內(nèi),隨函數(shù)的結(jié)束被釋放。

指針變量在創(chuàng)建時也是在內(nèi)存棧,里面的值是對象的地址,當用new操作符時會在內(nèi)存堆上分配一個空間,即存儲實際的對象內(nèi)容,此時的指針變量里的值即為剛剛分配的內(nèi)存地址。所以為什么要用delete釋放呢?這是因為內(nèi)存棧里的變量會隨著函數(shù)的結(jié)束而釋放,內(nèi)存堆里的內(nèi)容需要用戶手動釋放,所以當函數(shù)調(diào)用結(jié)束時,指針變量會被釋放,如果不先delete的話,內(nèi)存堆里的內(nèi)容就會找不到地址,也就"無人看管"了。所以在實際使用中一定要記得用完后delete,若是數(shù)組,則是delete[]。

作為函數(shù)參數(shù)的不同

類的對象和指針都可作為函數(shù)參數(shù)傳遞,這其中還可以有一個引用,代碼如下:

void func(CPerson object)
void func(CPerson* object)
void func(CPerson &object)

那么這幾種方式有何區(qū)別呢?下面來一一分析一下。
1: void func(CPerson object)
這種函數(shù)是非常不建議的,因為函數(shù)參數(shù)壓棧時,對object進行了復制(還記得拷貝構(gòu)造函數(shù)嗎),所以函數(shù)對object的操作實際上是對新的對象空間進行的操作,不會影響原對象空間。由于不必要的拷貝對象是十分浪費時間的,也沒有意義,我們完全可以用函數(shù)func(const Cobject& object);來代替,同樣能保護對象的只讀性質(zhì)。
2:void func(CPerson object)
這種方式是將類指針作為參數(shù),函數(shù)壓入?yún)?shù)時實際上復制了指針的值(其實指針可以看作一個存放地址值的整形),實際復制的指針仍指向原對象的空間,所以func函數(shù)對該指針的操作是對原對象空間的操作。
3: void func(CPerson &object)
這種方式和傳指針類似,但函數(shù)壓入?yún)?shù)時實際上復制了object對象的this指針,其實this指針不是一個真正存在的指針,可以看作是每個對象的數(shù)據(jù)空間起始地址。func函數(shù)中對this指針的操作,實際上也是對原對象空間的操作。

不管值傳遞,引用傳遞啊亂七八遭的什么東西,反正調(diào)用函數(shù)時都是會復制參數(shù)的,只是不同的是復制的是地址,還是整個對象空間的區(qū)別而已。
相同的,函數(shù)CPerson func(CPerson& object);在return CPerson對象時,同樣會進行構(gòu)貝構(gòu)造。這些隱藏的對象復制都是不需要的,我們可以改為CPerson& func(CPerson& object);或是CPerson* func(CPerson& object);這樣,在return時,就只是對指針(地址)的復制而已。在不是特殊的情況下,不要將整個對象作為參數(shù),也不要返回整個對象。

類指針實現(xiàn)多態(tài)

還有一個顯著區(qū)別就是類指針可以實現(xiàn)多態(tài),通過分類指針調(diào)用子類對象,下面詳細說明。
C++的多態(tài)性用一句話概括就是:在基類的函數(shù)前加上virtual關(guān)鍵字,在派生類中重寫該函數(shù),運行時將會根據(jù)對象的實際類型來調(diào)用相應的函數(shù)。如果對象類型是派生類,就調(diào)用派生類的函數(shù);如果對象類型是基類,就調(diào)用基類的函數(shù)。

1:用virtual關(guān)鍵字申明的函數(shù)叫做虛函數(shù),虛函數(shù)肯定是類的成員函數(shù)。
2:存在虛函數(shù)的類都有一個一維的虛函數(shù)表叫做虛表,類的對象有一個指向虛表開始的虛指針。虛表是和類對應的,虛表指針是和對象對應的。
3:多態(tài)性是一個接口多種實現(xiàn),是面向?qū)ο蟮暮诵?,分為類的多態(tài)性和函數(shù)的多態(tài)性。
4:多態(tài)用虛函數(shù)來實現(xiàn),結(jié)合動態(tài)綁定.
5:純虛函數(shù)是虛函數(shù)再加上 = 0;
6:抽象類是指包括至少一個純虛函數(shù)的類。純虛函數(shù):virtual void fun()=0;即抽象類!必須在子類實現(xiàn)這個函數(shù),即先有名稱,沒有內(nèi)容,在派生類實現(xiàn)內(nèi)容。

下面看一個具體例子:

class CPerson
{
public:
    virtual void show()
    {
        cout<<"I am a people"<<endl;
    }
};

class CStudent:public CPerson
{
public:
    void show()
    {
        cout<<"I am a student"<<endl;
    }
};

int main()
{
    CStudent stu;
    CPerson *per = &stu;
    per->show();
    system("pause");
    return 0;
}

輸出的結(jié)果為:


運行jie

可以看到父類指針指向子類對象后,調(diào)用的是子類的show函數(shù),注意多態(tài)的實現(xiàn)需要在函數(shù)前加virtual修飾,使其為虛函數(shù),否則調(diào)用的還是父類的,總之要實現(xiàn)多態(tài),類指針和虛函數(shù)缺一不可。關(guān)于多態(tài)的詳細分析具體可以參考http://www.cnblogs.com/cxq0017/p/6074247.html

通過以上對類對象和類指針不同方面的分析,我們在知道在什么時候應該使用類對象,什么時候使用類指針比較好。


感謝您的閱讀!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

  • 1. 結(jié)構(gòu)體和共同體的區(qū)別。 定義: 結(jié)構(gòu)體struct:把不同類型的數(shù)據(jù)組合成一個整體,自定義類型。共同體uni...
    breakfy閱讀 2,271評論 0 22
  • const 引用 const 引用是指向 const 對象的引用:const int ival = 1024;co...
    rogerwu1228閱讀 741評論 0 1
  • 重新系統(tǒng)學習下C++;但是還是少了好多知識點;socket;unix;stl;boost等; C++ 教程 | 菜...
    kakukeme閱讀 20,455評論 0 50
  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 2,058評論 0 9
  • 前言 把《C++ Primer》[https://book.douban.com/subject/25708312...
    尤汐Yogy閱讀 9,676評論 1 51

友情鏈接更多精彩內(nèi)容