如下代碼:
- ...
- point pt1(2,3);
- point pt2=pt1; //Or point pt2(pt1);
- ...
上述代碼用物件pt1初始化pt2, 相當於將pt1中的每個成員數據的值複製於pt2中, 這是表面現象, 實際上系統調用一個複製構造函數. 如果類定義沒有顯示定義該複製構造函數時, 編譯器會隱式定義一個預設的複製構造函數, 它是一個inline, public 類型的成員函數, 其原型如下:
point::point(const point &);
當然可以顯示定義複製構造函數以完成其他動作, 在有的情況下系統提供的預設構造函數足以滿足需要, 但在某些場合的確必須客制定義構造函數.
範例代碼:
---------------------------Point8_9.h---------------------------
- #include "main.h"
- class Point8_9{
- int xPos;
- int yPos;
- public:
- Point8_9(int x=0,int y=0){
- cout << "<調用構造函數>" << endl;
- xPos = x;
- yPos = y;
- }
- Point8_9(const Point8_9& pt){
- cout << "<<調用複製構造函數>>" << endl;
- xPos = pt.xPos;
- yPos = pt.yPos;
- }
- void print(){
- cout << "xPos: " << xPos << ",yPos: " << yPos << endl;
- }
- };
- ...
- void example809(){
- Point8_9 pt1(3,4);
- pt1.print();
- Point8_9 pt2 = pt1;
- pt2.print();
- Point8_9 pt3;
- pt3.print();
- Point8_9 pt4(pt3);
- pt4.print();
- }
- ...
Ps. 一但顯示定義了構造函數, 編譯器便不會再提供預設的複製構造函數. "point pt2=pt1;" 等價於 "point pt2(pt1);". 另外如果成員變量為const或引用類型, 則需透過初始化表達式進行初始化.
預設複製構造函數帶來的問題:
預設的複製構造函數並非萬用, 在某些情況需由程序員顯示定義複製構造函數, 請參考如下代碼:
---------------------------Computer8_10.h---------------------------
- #include "main.h"
- class Computer8_10{
- char* brand;
- float price;
- public:
- Computer8_10(const char* sz,float p){
- brand = new char[strlen(sz)+1];
- strcpy(brand,sz);
- price = p;
- }
- ~Computer8_10(){
- if(brand!=NULL)
- delete[] brand;
- cout << "清理動態內存 brand" << endl;
- }
- void print(){
- cout << "品質: " << brand << endl;
- cout << "價格: " << price << endl;
- }
- };
- ...
- void example810(){
- Computer8_10 comp("Dell",9000);
- comp.print();
- Computer8_10 comp2(comp);
- comp2.print();
- }
- ...
按造預設複製構造函數, 語句"Computer8_10 comp2(comp);" 等價於如下代碼:
其中後一句"comp2.price=comp1.price;" 是沒有問題的, 但 "comp2.brand = comp1.brand;" 卻給程序帶來致命的問題, 經過賦值操作後, 兩個對象中的brand指針都是指向同一塊動態內存, 當comp1, comp2撤銷時, 其釋放函數都要釋放同一塊內存, 可是對像的撤銷有先後, 一旦一個對像被撤銷後, 另一個對像的brand指針變成了 wild 指針, 使用該指針在次釋放動態內存將會引發內存錯誤. 不僅是重複釋放內存問題, 預設複製構造函數還有可能為程序帶來不可預測錯誤.
沒有留言:
張貼留言