淺談C++中對象的復制與對象之間的互相賦值。本站提示廣大學習愛好者:(淺談C++中對象的復制與對象之間的互相賦值)文章只能為提供參考,不一定能成為您想要的結果。以下是淺談C++中對象的復制與對象之間的互相賦值正文
C++對象的復制
有時須要用到多個完整雷同的對象,例如,統一型號的每個產物從表面到外部屬性都是一樣的,假如要對每個產物分離停止處置,就須要樹立多個異樣的對象,並要停止雷同的初始化,用之前的方法界說對象(同時初始化)比擬費事。另外,有時須要將對象在某一瞬時的狀況保存上去。
C++供給了克隆對象的辦法,來完成上述功效。這就是對象的復制機制。
用一個已有的對象疾速地復制出多個完整雷同的對象。如
Box box2(box1);
其感化是用已有的對象box1去克隆出一個新對象box2。
其普通情勢為:
類名 對象2(對象1);
用對象1復制出對象2。
可以看到,它與界說對象的方法相似,然則括號中給出的參數不是普通的變量,而是對象。在樹立對象時挪用一個特別的結構函數——復制結構函數(copy constructor)。這個函數的情勢是如許的:
//The copy constructor definition. Box::Box(const Box& b) { height=b.height; width=b.width; length=b.length; }
復制結構函數也是結構函數,但它只要一個參數,這個參數是本類的對象(不克不及是其他類的對象), 並且采取對象的援用的情勢(普通商定加const聲明,使參數值不克不及轉變,以避免在挪用此函數時因失慎而使對象值被修正)。此復制結構函數的感化就是將實參對象的各成員值逐個賦給新的對象中對應的成員。
復制對象的語句
Box box2(box1);
這現實上也是樹立對象的語句,樹立一個新對象box2。因為在括號內給定的實參是對象,是以編譯體系就挪用復制結構函數(它的形參也是對象), 而不會去挪用其他結構函數。實參box1的地址傳遞給形參b(b是box1的援用),是以履行復制結構函數的函數體時,將box1對象中各數據成員的值賦給box2中各數據成員。
假如用戶本身不決義復制結構函數,則編譯體系會主動供給一個默許的復制結構函數,其感化只是簡略地復制類中每一個數據成員。C++還供給另外一種便利用戶的復制情勢,用賦值號取代括號,如
Box box2=box1; //用box1初始化box2
其普通情勢為
類名 對象名1 = 對象名2;
可以在一個語句中停止多個對象的復制。如
Box box2=box1,box3=box2;
按box1來復制box2和box3。可以看出,這類情勢與變量初始化語句相似,請與上面界說變量的語句作比擬:
int a=4,b=a;
這類情勢看起來很直不雅,用起來很便利。然則其感化都是挪用復制結構函數。
請留意對象的復制和對象的賦值在概念上和語法上的分歧。對象的賦值是對一個曾經存在的對象賦值,是以必需先界說被賦值的對象,能力停止賦值。而對象的復制則是從無到有地樹立一個新對象,並使它與一個已有的對象完整雷同(包含對象的構造和成員的值)。
可以對例子法式中的主函數作一些修正:
int main( ) { Box box1(15,30,25); //界說box1 cout<<"The volume of box1 is "<<box1.volume( )<<endl; Box box2=box1,box3=box2; //按box1來復制box2,box3 cout<<"The volume of box2 is "<<box2.volume( )<<endl; cout<<"The volume of box3 is "<<box3.volume( )<<endl; }
履行完第3行後,3個對象的狀況完整雷同。
上面說一下通俗結構函數和復制結構函數的差別。
1) 在情勢上
類名(形參表列); //通俗結構函數的聲明,如Box(int h,int w,int len);
類名(類名& 對象名); //復制結構函數的聲明,如Box(Box &b);
2) 在樹立對象時,實參類型分歧
體系會依據實參的類型決議挪用通俗結構函數或復制結構函數。如
Box box1(12,15,16); //實參為整數,挪用通俗結構函數 Box box2(box1); //實參是對象名,挪用復制結構函數
3) 在甚麼情形下被挪用
通俗結構函數在法式中樹立對象時被挪用。復制結構函數在用已有對象復制一個新對象時被挪用,在以下3種情形下須要克隆對象:
① 法式中須要新樹立一個對象,並用另外一個同類的對象對它初始化,如下面引見的那樣。
② 當函數的參數為類的對象時。在挪用函數時須要將實參對象完全地傳遞給形參,也就是須要樹立一個實參的拷貝,這就是按實參復制一個形參,體系是經由過程挪用復制結構函數來完成的,如許能包管形參具有和實參完整雷同的值。如
void fun(Box b) //形參是類的對象 { } int main( ) { Box box1(12,15,18); fun(box1); //實參是類的對象,挪用函數時將復制一個新對象b return 0; }
③ 函數的前往值是類的對象。在函數挪用終了將前往值帶回函數挪用處時。此時須要將函數中的對象復制一個暫時對象並傳給該函數的挪用處。如
Box f( ) //函數f的類型為Box類類型 { Box box1(12,15,18); return box1; //前往值是Box類的對象 } int main( ) { Box box2; //界說Box類的對象box2 box2=f( ); //挪用f函數,前往Box類的暫時對象,並將它賦值給box2 }
以上幾種挪用復制結構函數都是由編譯體系主動完成的,不用由用戶本身去挪用,讀者只需曉得在這些情形下須要挪用復制結構函數便可以了。
C++對象之間互相賦值
假如對一個類界說了兩個或多個對象,則這些同類的對象之間可以相互賦值,或許說,一個對象的值可以賦給另外一個同類的對象。這裡所指的對象的值是指對象中一切數據成員的值。
對象之間的賦值也是經由過程賦值運算符“=”停止的。原來,賦值運算符“=”只能用來對單個的變量賦值,如今被擴大為兩個同類對象之間的賦值,這是經由過程對賦值運算符的重載完成的。
現實這個進程是經由過程成員復制來完成的,行將一個對象的成員值逐個復制給另外一對象的對應成員。
對象賦值的普通情勢為:
對象名1 = 對象名2;
留意對象名1和對象名2必需屬於統一個類。例如
Student stud1,stud2; //界說兩個同類的對象 stud2=stud1; //將stud1賦給stud2
經由過程上面的例子可以懂得如何停止對象的賦值。
[例] 對象的賦值。
#include <iostream> using namespace std; class Box { public : Box(int =10,int =10,int =10); //聲明有默許參數的結構函數 int volume( ); private : int height; int width; int length; }; Box::Box(int h,int w,int len) { height=h; width=w; length=len; } int Box::volume( ) { return (height*width*length); //前往體積 } int main( ) { Box box1(15,30,25),box2; //界說兩個對象box1和box2 cout<<"The volume of box1 is "<<box1.volume( )<<endl; box2=box1; //將box1的值賦給box2 cout<<"The volume of box2 is "<<box2.volume( )<<endl; return 0; }
運轉成果以下:
The volume of box1 is 11250 The volume of box2 is 11250
解釋:
對象的賦值只對個中的數據成員賦值,而纰謬成員函數賦值。數據成員是占存儲空間的,分歧對象的數據成員占領分歧的存儲空間,賦值的進程是將一個對象的數據成員在存儲空間的狀況復制給另外一對象的數據成員的存儲空間。而分歧對象的成員函數是統一個函數代碼段,不須要、也沒法對它們賦值。
類的數據成員中不克不及包含靜態分派的數據,不然在賦值時能夠湧現嚴重效果 (在此不作具體剖析,只需記住這一結論便可)。