程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++學習-類對象的復制控制(5)

C++學習-類對象的復制控制(5)

編輯:C++入門知識

前面學習了構造函數的用法與初始化列表的特性,本章還是學習構造函數的內容。類型還能控制復制、賦值或撤銷該類型的對象,這時候,類通過特殊的成員函數:復制構造函數、賦值操作符和析構函數來控制這些行為。這些都屬於類對象的復制控制,挺重要的一部分內容。

 


一、本文內容的應用

1.復制構造函數的例子:
string str1("hello");
string str2(str1);
2.賦值操作符的例子:
string str1("hello");
string str2 = str1;

二、復制構造函數的應用於哪些地方
什麼樣的函數才是復制構造函數?
只有單個形參,而且該形參是對本類類型對象的引用(常用const修飾)。
復制構造函數用於:
1.用一個同類型的對象顯示或隱式初始化一個對象。
eg:
string str1("hello");
string str2(str1);
2.作為函數的實參
eg:
void Show(string str);
...
string str1("hello");
Show(str1); //存在一個復制操作,將str1對象隱式復制到Show函數的臨時對象

 


3.作為函數的返回值

eg:
string getString() const
{
string str("hello");
...
return str;
}
...
string str1 = getString(); //將getString函數的返回值的string對象復制到str1對象

 


4.初始化順序容器的元素

eg:
vector<string> vec(5); //聲明了一個vector,包含5個string對象;
//編譯器首先使用string默認構造函數創建一個臨時對象來初始化vec,然後使用復制構造函數將臨時值復制到vec的每個元素中。

 


5.根據元素初始化式列表初始化數組元素

這裡要強調的是:初始化式列表
a.每個元素調用一次默認構造函數
string str[10]; //調用了10次默認構造函數
b.每個元素調用一次復制構造函數
string str1, str2, str3, str4;
string str[] = { str1, str2, str3, str4};

三、合成的復制構造函數和合成的賦值操作符
如果用戶沒有顯示的定義復制構造函數或賦值操作符,編譯器將會默認的合成一個復制構造函數。復制構造函數與合成復制構造函數,或者賦值操作符與合成賦值操作符不同,編譯器默認合成的函數的行為是"逐個成員初始化",將新對象初始化為原對象的副本。逐個成員初始化不包括static成員,只負責初始化非static成員。

四、小試牛刀

這裡編寫一個最簡單的例子,來展示一下類對象的復制控制。


[cpp] #include <iostream>  
 
using namespace std; 
 
class CObj 

public: 
    CObj() 
    { 
        cout << "默認構造函數" << endl; 
    } 
    CObj(const CObj &obj) 
    { 
        cout << "復制構造函數" << endl; 
    } 
    CObj & operator=(const CObj &obj) 
    { 
        if (&obj != this) 
        { 
            cout << "賦值操作符" << endl; 
        } 
        return *this; 
    } 
}; 
 
int main() 

    CObj obj1; 
    cout << endl; 
 
    CObj obj2(obj1); 
    cout << endl; 
 
    CObj obj3; 
    obj3 = obj2; 
    return 0; 

#include <iostream>

using namespace std;

class CObj
{
public:
    CObj()
    {
        cout << "默認構造函數" << endl;
    }
    CObj(const CObj &obj)
    {
        cout << "復制構造函數" << endl;
    }
    CObj & operator=(const CObj &obj)
    {
        if (&obj != this)
        {
            cout << " www.2cto.com 賦值操作符" << endl;
        }
        return *this;
    }
};

int main()
{
    CObj obj1;
    cout << endl;

    CObj obj2(obj1);
    cout << endl;

    CObj obj3;
    obj3 = obj2;
    return 0;
}
執行結果:

 

[plain] 默認構造函數 
 
復制構造函數 
 
默認構造函數 
賦值操作符 
默認構造函數

復制構造函數

默認構造函數
賦值操作符
四、禁止復制
1.有些類需要完全禁止復制,怎麼辦?
只需將復制構造函數聲明為私有成員函數即可。
解釋:因為如果不聲明定義,編譯器將會默認合成一個復制構造函數。
例子:

 

[cpp] #include <iostream>  
 
using namespace std; 
 
class CObj 

public: 
    CObj() 
    { 
        cout << "默認構造函數" << endl; 
    } 
private: 
    CObj(const CObj &obj) 
    { 
        cout << "復制構造函數" << endl; 
    } 
}; 
 
int main() 

    CObj obj1; 
    CObj obj2(obj1); 
 
    return 0; 

#include <iostream>

using namespace std;

class CObj
{
public:
    CObj()
    {
        cout << "默認構造函數" << endl;
    }
private:
    CObj(const CObj &obj)
    {
        cout << "復制構造函數" << endl;
    }
};

int main()
{
    CObj obj1;
    CObj obj2(obj1);

    return 0;
}
編譯報錯:


error: 'CObj::CObj(const CObj&)' is private


這就是禁止復制的效果,正是這裡想要的。

 

 

2.連友元函數和成員函數的復制也要禁止,怎麼辦?
如果想要連友元函數和成員函數的復制也禁止,那麼可以聲明一個私有的復制構造函數但不對其定義。
解釋:因為友元函數或成員函數可以訪問到類的私有成員,所以當然能調用私有的復制構造函數,所有將復制構造函數聲明為私有但不定義,就能避免友元或成員函數的調用。
例子:

 

[cpp] #include <iostream>  
 
using namespace std; 
 
class CObj 

public: 
    CObj() 
    { 
        cout << "默認構造函數" << endl; 
    } 
    friend void fcopy(); 
private: 
    CObj(const CObj &obj); 
}; 
 
void fcopy() 

    CObj obj1; 
    CObj obj2(obj1); 

 
int main() 

    fcopy(); 
 
    return 0; 

#include <iostream>

using namespace std;

class CObj
{
public:
    CObj()
    {
        cout << "默認構造函數" << endl;
    }
    friend void fcopy();
private:
    CObj(const CObj &obj);
};

void fcopy()
{
    CObj obj1;
    CObj obj2(obj1);
}

int main()
{
    fcopy();

    return 0;
}
編譯報錯:
undefined reference to `CObj::CObj(CObj const&)'
這也正是這裡需要的結果,禁止復制成功,OK。

 

再接再厲!

摘自 gzshun的專欄
 

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