指向對象的指針 在建立對象的時候,變異系統會給每一個對象分配一定的存儲空間,以存放其成員。 對象空間的起始地址就是對象的指針。可以定義一個指針變量,用來存放對象的指針。 一個簡單的示例1.1: [cpp] #include<iostream> using namespace std; class Student { public: int num; int score; Student(int ,int );//聲明構造函數 void Print();//聲明輸出信息函數 }; Student::Student(int n,int s) { num=n; score=s; } void Student::Print(){ cout<<num<<"\t"<<score<<endl; } int main(){ Student stud(1,100);//實例化一個對象 Student *p=&stud;//定義一個指向對象的指針,並使用對象stud的地址初始化 cout<<"*p.num:"<<(*p).num<<endl;//使用指向對象的指針調用數據成員的方式一 cout<<"p->score:"<<p->score<<endl;//使用指向對象的指針調用數據成員的方式二 (*p).Print(); p->Print(); return 0; } 指向對象成員的指針 對象有地址,存放對象初始地址的指針變量就是指向對象的指針變量。 對象中的成員也有地址,存放對象成員地址的指針變量就是指向對象成員的指針變量。 1.指向對象數據成員的指針 定義指向對象數據成員的方法和定義指向普通變量的方法相同: 數據類型 * 指針變量名 [cpp] p=&t1.hour;//將對象t1的數據成員hour的地址賦給p,p指向t1.hour cout<<*p<<endl;//輸出t1.hour的值 2.指向對象成員函數的指針 定義指向成員函數的指針和定義指向普通函數的指針的方法是不同的。 定義指向普通函數的指針的方法是這樣的: 數據類型名(* 指針變量名)(參數列表); 如: [cpp void (*p)(int n,int m);//p是指向void型函數的指針變量 p=fun;//將fun函數的入口地址賦給指針變量p,p就指向了函數fun (*p)(a,b);//調用fun函數,其中,a,b是實參 而定義一個指向對象成員函數的指針變量則比較復雜一些。 如果我們直接按照上面的方法定義指針變量,將對象成員函數名賦給指針變量p: [cpp] void (*p)(); p=t1.Print(); 編譯會出現錯誤 成員函數與普通函數的一個最根本區別:它是類中的一個成員。 編譯系統要求上面的復制語句中,指針變量的類型必須與賦值號右側函數的類型相匹配,要求在一下3個方面要匹配: 1.函數參數的類型和參數個數 2.函數返回值的類型 3.所屬的類 前兩個是匹配的,而第三點不匹配。 指針變量p與類無關,而Print()卻屬於Student類。 要定義指向成員函數的指針變量應該采用以下形式: [cpp] void (Student::*p)();//定義p為指向Student類中公共成員函數的指針變量 數據類型名(類名::*指針變量名)(參數表列); 我們知道,所有的Student類實例化得到的對象都是公用一個成員函數的,所以我們沒有必要指定它是指向那個對象的成員函數的指針,我們只需要定義它是指向該類的成員函數就可以了。 使指針變量指向一個公用成員函數的一般形式為: [cpp] p=&Student::Print; 指針變量名=&類名::成員函數名; 在使用時,仍然需要將指針放到具體的對象中使用,(*p)的作用等價於Print() [cpp] stud.(*p);//作用與stud.Print()的作用等價 =================一個使用對象指針的例子1.2=========== [cpp] #include<iostream> using namespace std; class Student { public: int num; int score; Student(int ,int ); void Print(); }; Student::Student(int n,int s) { num=n; score=s; } void Student::Print(){ cout<<num<<"\t"<<score<<endl; } int main(){ Student stud(1,100); cout<<"stud.Print()"<<endl; stud.Print();//直接調用對象stud的成員函數Print(); Student *p_class=&stud;//定義指向對象stud的指針; cout<<"p_class->Print()"<<endl; p_class->Print();//通過指向對象的指針調用成員函數Print(); void (Student::*p_fun)();//聲明p_fun是指向Student中的函數的指針 p_fun=&Student::Print;//是p_fun指向Student類公用成員函數Print() cout<<"(stud.*p_fun)()"<<endl; (stud.*p_fun)();//調用對象stud中的p_fun所指向的成員函數(即:stud.Print) return 0; } this指針 每個對象中的數據成員都分別占用存儲空間,如果對同一個類定義了n個對象,則有n組同樣大小的空間一存放n個對象中的數據成員。 單數不同的對象都調用同一段函數代碼段。 那麼,當不同對象的成員函數引用數據成員時,怎麼能保證引用的是所制定的對象的數據成員呢? 實際上,在每一個成員函數中,都包含一個特殊的指針,這個指針的名字是固定的,稱為this指針。 它是指向本類對象的指針,它的值是當前被調用的成員函數所在的對象的起始地址。 例如: Print()函數中 [cpp] cout<<num<<"\t"<<score<<endl; 實際上是 [cpp] view plaincopy cout<<this->num<<"\t"<<this->score<<endl; this指針式隱式使用的,它是作為參數被傳遞給成員函數。 在程序中的函數: [cpp] void Student::Print(){ cout<<num<<"\t"<<score<<endl; } C++編譯系統會自動處理成: [cpp] void Student::Print(Student *this){ cout<<this->num<<"\t"<<this->score<<endl; } 即在成員函數的形參表列中增加一個this指針。在調用成員函數stud.Print()時,實際上是用以下方式調用的: [cpp] stud.Print(&stud);