程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> C++基本之this指針與另外一種“多態”

C++基本之this指針與另外一種“多態”

編輯:關於C++

C++基本之this指針與另外一種“多態”。本站提示廣大學習愛好者:(C++基本之this指針與另外一種“多態”)文章只能為提供參考,不一定能成為您想要的結果。以下是C++基本之this指針與另外一種“多態”正文


1、引入
界說一個類的對象,起首體系曾經給這個對象分派了空間,然後會挪用結構函數。

一個類有多個對象,當法式中挪用對象的某個函數時,有能夠要拜訪到這個對象的成員變量。
而關於統一個類的每個對象,都是同享統一份類函數。對象有零丁的變量,然則沒有零丁的函數,所以當挪用函數時,體系必需讓函數曉得這是哪一個對象的操作,從而肯定成員變量是哪一個對象的。
這類用於對成員變量歸屬對像停止辨別的器械,就叫做this指針。現實上它就是對象的地址,這一點從反匯編出來的代碼可以看到。

2、剖析
1、測試代碼:

/////////////////////////////////////////////////////////////////////////////////////
#include<iostream>
using   namespace   std;
/////////////////////////////////////////////////////
class A
{
public:
    A(char *szname)
    {
        cout<<"construct"<<endl;
        name
 = new char[20];
        strcpy(name,
 szname);
    }
    ~A()
    {
        cout<<"destruct"<<endl;
        delete name;
    }
    void    show();
private:
    char    *name;
};
/////////////////////////////////////////////////////
void    A::show()
{
    cout<<"name
 = "<<name<<endl;
}
/////////////////////////////////////////////////////
int main()
{
    A
 a("zhangsan");
    a.show();
    system("pause");
    return 0;
}

法式在VC++6.0 32位操作體系上編譯、運轉。
對編譯後的EXE文件,停止反匯編。反匯編對象為OllyDbg。

2、反匯編剖析
症結點截圖以下:
(1)從圖1可以發明this指針經由過程ECX存放器,傳遞給了成員函數。this指針就是對象的地址。

圖 1 Main函數

(2)從圖 2可以發明拜訪對象的成員變量用的就是之前經由過程ECX傳入的this指針。

 

圖 2 show()函數

3、深刻懂得

經由過程截圖及相干的材料,可以很清楚的曉得在挪用結構函數、show()函數之前的誰人ECX就是this指針,也就是說這是一個驗證性的試驗,謎底曾經很清晰了,所要做的就是去著手體驗一下。然則,假設我不懂C++、我不懂甚麼this指針,我一樣可以發明這個叫做“this指針”的器械。經由過程OD的靜態調試,當顯示出了name時,慢慢回溯可以發明name的泉源是ECX。OD從新載入,檢查在進入show()函數之前ECX是哪裡來的,終究可以一步步的發明,ECX就是一個地址,這個地址裡邊的第一個值也是一個地址,指向一串字符串。再往上剖析,進入show()上邊的結構函數,可以發明裡邊有new操作,strcpy操作,這裡就發明了字符串空間、內容的起源。至此,根本就剖析完了。

經由過程這個進程可以發明許多C++的常識。如:對象的空間是在挪用結構函數之前就分派好了的;對象裡邊沒有函數;this指針經由過程存放器ECX傳遞;經由過程聲明界說的對象它的空間分派在棧中;等等這些跟體系或許C++有聯系關系的常識。

然則,關於一個不懂C++的人看來,下面一段的領會都是沒有的。從匯編指令看不出C++的思惟,this指針不外是一個地址;對象不外是一些空間;結構函數、析構函數和其它的函數,也不外是一堆指令的聚集。

C++的統一個類界說出來的多個對象,從匯編指令看來是如許的:有許多塊地址空間,它們有雷同的年夜小。當分歧的對象挪用成員函數時,在匯編指令看來是:它們都call統一個地址,這個call指令其實裡邊是一個jmp指令,用於跳向某個地位,在call指令之前普通都邑把一個地址放到ECX中,固然有時刻會用客棧或許其它存放器。

C++的繼續、多態、封裝,對匯編法式員來講是看不出有甚麼奇異的,關於C++法式員來講那可就分歧了,可以省去許多的任務,把許多工作都交給了編譯器,讓編譯器主動給你弄定。

C++法式員所評論辯論的對象及其浩瀚的特色、長處,終究照樣釀成了“初級”的指令,並且能夠是效力低下的指令,即使如斯,它的長處仍弘遠於缺陷,它讓編程變得輕易、高效。

4、延長

溘然想到了C++的多態,一句話“將子類類型的指針賦值給父類類型的指針”,多態是經由過程虛函數完成。對虛函數及其相干內容的道理、具體懂得就不細說了。

說下我的簡略懂得,有一個基類A和子類B、C,有一個函數以基類A的指針為參數,然後在函數外頭經由過程指針挪用基類的成員函數。假設這個被挪用的基類成員函數不是虛函數,那末是弗成能完成多態的,由於翻譯成匯編指令的時刻,挪用成員函數的這個處所是一個call指令,然後這個call指令跳到某個處所去履行,這是一個固定了的地址。經由過程界說為虛函數,挪用成員函數的這個處所是經由過程虛函數表指針來肯定挪用哪一個函數的,而虛函數表指針就放在對象的地址空間中,假如對象變了,那末虛函數表指針也變了,挪用的函數也就分歧了。關於誰人以基類A的指針為參數的函數,指針等於對象的地址,假如傳遞的地址是子類B或許C的對象的地址,那末虛函數表指針也就分歧了,挪用的成員函數也就分歧了。

這就是多態,這類多態使得挪用統一個函數,由於傳遞參數的分歧而顯示出差別,參數可所以基類對象或許浩瀚分歧的子類對象。它們的差別是類與類之間的。

有虛函數的對象的內存結構,比沒有虛函數的對象多了一個指向虛函數表的指針。由於虛函數的挪用是經由過程虛函數表指針來完成的,所以有了多態。

再斟酌一下C++的this指針,一個類中的成員函數,根據this指針來辨別分歧的對象,也就是說依據this指針完成了拜訪分歧的對象的成員變量。

這能否也是多態的一種表示?這裡所說的多態曾經不是誰人“父類指針指向子類對象”的教條了,而是表現在統一個類的分歧對象之間,挪用統一個成員函數,根據參數“this指針”來完成拜訪分歧的對象的成員變量。成員函數拜訪成員變量,在編譯期沒法肯定它拜訪的成員變量在哪個地址的,只要到了運轉期根據this指針能力肯定拜訪的地址。這一點很相似於類的多態:以基類指針為參數的函數裡挪用了某個基類的虛成員函數,在編譯期沒法肯定法式運轉時挪用的會是哪一個類的對象,只要到了運轉期才肯定會挪用哪一個類的對象。

this指針辨認了統一個類的分歧的對象,換句話說,this指針使得成員函數可以拜訪統一個類的分歧對象。再深刻一點,this指針使得成員函數會由於this指針的分歧而拜訪到了分歧的成員變量。這也是多態吧,只是它是必定存在的多態,這類多態跟基類與派生類之間的多態是分歧級其余多態,它不像普通的多態可以經由過程對應用虛函數的選擇來棄取,它是一個類對應多個對象、多個對象同享一份成員函數代碼帶來的必定成果。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved