詳解C++中的對象指針與對象數組。本站提示廣大學習愛好者:(詳解C++中的對象指針與對象數組)文章只能為提供參考,不一定能成為您想要的結果。以下是詳解C++中的對象指針與對象數組正文
C++對象指針
指向對象的指針
在樹立對象時,編譯體系會為每個對象分派必定的存儲空間,以寄存其成員。對象空間的肇端地址就是對象的指針。可以界說一個指針變量,用來寄存對象的指針。
假如有一個類:
class Time { public : int hour; int minute; int sec; void get_time( ); }; void Time::get_time( ) { cout<<hour<<":"<<minute<<":"<<sec<<endl; }
在此基本上有以下語句:
Time *pt; //界說pt為指向Time類對象的指針變量 Time t1; //界說t1為Time類對象 pt=&t1; //將t1的肇端地址賦給pt
如許,pt就是指向Time類對象的指針變量,它指向對象t1。
界說指向類對象的指針變量的普通情勢為:
類名 *對象指針名;
可以經由過程對象指針拜訪對象和對象的成員。如:
*pt //pt所指向的對象,即t1 (*pt).hour //pt所指向的對象中的hour成員,即t1.hour pt->hour //pt所指向的對象中的hour成員,即t1.hour (*pt).get_time ( ) //挪用pt所指向的對象中的get_time函數,即t1.get_time pt->get_time ( ) //挪用pt所指向的對象中的get_time函數,即t1.get_time
下面第2, 3行的感化是等價的,第4, 5兩行也是等價的。
指向對象成員的指針
對象有地址,寄存對象初始地址的指針變量就是指向對象的指針變量。對象中的成員也有地址,寄存對象成員地址的指針變量就是指向對象成員的指針變量。
1) 指向對象數據成員的指針
界說指向對象數據成員的指針變量的辦法和界說指向通俗變量的指針變量辦法雷同。例如:
int *p1; //界說指向整型數據的指針變量
界說指向對象數據成員的指針變量的普通情勢為:
數據類型名 *指針變量名;
假如Time類的數據成員hour為公用的整型數據,則可以在類外經由過程指向對象數據成員的指針變量拜訪對象數據成員hour:
p1=&t1.hour; //將對象t1的數據成員hour的地址賦給p1,p1指向t1.hour cout<<*p1<<endl; //輸入t1.hour的值
2) 指向對象成員函數的指針
須要提示讀者留意: 界說指向對象成員函數的指針變量的辦法和界說指向通俗函數的指針變量辦法有所分歧。這裡重溫一個指向通俗函數的指針變量的界說辦法:
數據類型名 (*指針變量名) (參數表列);
如
void ( *p)( ); //p是指向void型函數的指針變量
可使它指向一個函數,並經由過程指針變量挪用函數:
p = fun; //將fun函數的生齒地址傳給指針變童p,p就指向了函數fn
(*P)( ); //挪用fn函數
而界說一個指向對象成員函數的指針變量則比擬龐雜一些。假如模擬下面的辦法將對象成員函數名賦給指針變最P:
p = t1.get_time;
則會湧現編譯毛病。為何呢?
成員函數與通俗函數有一個最基本的差別: 它是類中的一個成員。編譯體系請求在下面的賦值語句中,指針變量的類型必需與賦值號右邊函數的類型相婚配,請求在以下3方面都要婚配:
①函數參數的類型和參數個數;
②函數前往值的類型;
③所屬的類。
如今3點中第①②兩點是婚配的,而第③點不婚配。指針變量p與類有關,面get_ time函數卻屬於Time類。是以,要差別通俗函數和成員函數的分歧性質,不克不及在類外直接用成員函數名作為函數進口地址去挪用成員函數。
那末,應當如何界說指向成員函數的指針變量呢?應當采取上面的情勢:
void (Time::*p2)( ); //界說p2為指向Time類中公用成員函數的指針變量
留意:(Time:: *p2) 兩側的括號不克不及省略,由於()的優先級高於*。假如無此括號,就相當於:
void Time::*(p2()) //這是前往值為void型指針的函數
界說指向公用成員函數的指針變量的普通情勢為:
數據類型名 (類名::*指針變量名)(參數表列);
可讓它指向一個公用成員函數,只需把公用成員函數的進口地址賦給一個指向公用成員函數的指針變量便可。如:
p2=&Time::get_time;
使指針變量指向一個公用成員函數的普通情勢為
指針變量名=&類名::成員函數名;
在VC++體系中,也能夠不寫&,以和C說話的用法分歧,但建議在寫C++法式時不要省略&。
[例]有關對象指針的應用辦法。
#include <iostream> using namespace std; class Time { public: Time(int,int,int); int hour; int minute; int sec; void get_time( ); }; Time::Time(int h,int m,int s) { hour=h; minute=m; sec=s; } void Time::get_time( ) //聲明私有成員函數 //界說私有成員函數 { cout<<hour<<":"<<minute<<":" <<sec<<endl; } int main( ) { Time t1(10,13,56); //界說Time類對象t1 int *p1=&t1.hour; //界說指向整型數據的指針變量p1,並使p1指向t1.hour cout<<* p1<<endl; //輸入p1所指的數據成員t1.hour t1.get_time( ); //挪用對象t1的成員函數get_time Time *p2=&t1; //界說指向Time類對象的指針變量p2,並使p2指向t1 p2->get_time( ); //挪用p2所指向對象(即t1)的get_time函數 void (Time::*p3)( ); //界說指向Time類公用成員函數的指針變量p3 p3=&Time::get_time; //使p3指向Time類公用成員函數get_time (t1.*p3)( ); //挪用對象t1中p3所指的成員函數(即t1.get_time( )) return 0; }
法式運轉成果為:
10 (main函數第4行的輸入) 10:13:56 (main函數第5行的輸入) 10:13:56 (main函數第7行的輸入) 10:13:56 (main函數第10行的輸入)
可以看到為了輸入t1中hour,minute和sec的值,可以采取3種分歧的辦法。
幾點解釋:
1) 從main函數第9行可以看出,成員函數的進口地址的准確寫法是:
&類名::成員函數名
不該該寫成:
p3 =&t1.get_time; //t1為對象名
成員函數不是寄存在對象的空間中的,而是寄存在對象外的空間中的。假如有多個同類的對象,它們共用統一個函數代碼段。是以賦給指針變量p3的應是這個公用的函數代碼段的進口地址。
挪用t1的get_time函數可以用t1.get_time()情勢,那是從邏輯的角度而言的,經由過程對象名能挪用成員函數。而如今法式語句中須要的是地址,它是物理的,詳細地址是和類而不是對象相接洽的。
2) main函數第8, 9兩行可以合寫為一行:
void (Time::*p3)( )=&Time::get_time; //界說指針變量時指定其指向
C++對象數組
數組不只可以由簡略變量構成(例如整型數組的每個元素都是整型變量),也能夠由對象構成(對象數組的每個元素都是同類的對象)。
在平常生涯中,有很多實體的屬性是配合的,只是屬性的詳細內容分歧。例如一個班有50個先生,每一個先生的屬性包含姓名、性別、年紀、成就等。假如為每個先生樹立一個對象,須要分離取50個對象名。用法式處置很不便利。這時候可以界說一個“先生類”對象數組,每個數組元素是一個“先生類”對象。例如
Student stud[50]; //假定已聲清楚明了Student類,界說stud數組,有50個元素
在樹立數組時,異樣要挪用結構函數。假如有50個元素,須要挪用50次結構函數。
在須要時可以在界說數組時供給實參以完成初始化。假如結構函數只要一個參數,在界說數組時可以直接在等號前面的花括號內供給實參。如
Student stud[3]={60,70,78}; //正當,3個實參分離傳遞給3個數組元素的結構函數
假如結構函數有多個參數,則不克不及用在界說數組時直接供給一切實參的辦法,由於一個數組有多個元素,對每一個元素要供給多個實參,假如再斟酌到結構函數有默許參數的情形,很輕易形成實介入形參的對應關系不清楚,湧現歧義性。例如,類Student的結構函數有多個參數,且為默許參數:
Student:: Student(int=1001,int=18,int=60); //界說結構函數,有多個參數,且為默許參數
假如界說對象數組的語句為
Student stud[3]={1005,60,70};
在法式中最好不要采取這類輕易惹起歧義性的辦法。
編譯體系只為每一個對象元素的結構函數傳遞一個實參,所以在界說數組時供給的實參個數不克不及跨越數組元素個數,如
Student stud[3]={60,70,78,45}; //不正當,實參個數跨越對象數組元素個數
那末,假如結構函數有多個參數,在界說對象數組時應該如何完成初始化呢?答復是: 在花括號平分別寫出結構函數並指定實參。
假如結構函數有3個參數,分離代表學號、年紀、成就。則可以如許界說對象數組:
Student Stud[3]={ //界說對象數組 Student(1001,18,87), //挪用第1個元素的結構函數,為它供給3個實參 Student(1002,19,76), //挪用第2個元素的結構函數,為它供給3個實參 Student(1003,18,72) //挪用第3個元素的結構函數,為它供給3個實參 };
在樹立對象數組時,分離挪用結構函數,對每一個元素初始化。每個元素的實參分離用括號包起來,對應結構函數的一組形參,不會混雜。
[例] 對象數組的應用辦法。
#include <iostream> using namespace std; class Box { public : //聲明有默許參數的結構函數,用參數初始化表對數據成員初始化 Box(int h=10,int w=12,int len=15): height(h),width(w),length(len){ } int volume( ); private : int height; int width; int length; }; int Box::volume( ) { return (height*width*length); } int main( ) { Box a[3]={ //界說對象數組 Box(10,12,15), //挪用結構函數Box,供給第1個元素的實參 Box(15,18,20), //挪用結構函數Box,供給第2個元素的實參 Box(16,20,26) //挪用結構函數Box,供給第3個元素的實參 }; cout<<"volume of a[0] is "<<a[0].volume( )<<endl; cout<<"volume of a[1] is "<<a[1].volume( )<<endl; cout<<"volume of a[2] is "<<a[2].volume( )<<endl; return 0; }
運轉成果以下:
volume of a[0] is 1800 volume of a[1] is 5400 volume of a[2] is 8320