日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

浅谈C++类(6)--复制构造函数

發(fā)布時間:2023/12/4 c/c++ 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 浅谈C++类(6)--复制构造函数 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

歡迎轉載,但請標明作者 “九天雁翎”,當然,你給出這個帖子的鏈接更好。

還記得(1)中講到的構造函數(shù)嗎?復習一下,這次我們重載一個新的默認構造函數(shù)--即當你不給出初始值時調用的構造函數(shù),我記得我講過這個概念吧,有嗎?看下面的例子。

例6.0

#include <string>
#include <iostream>
using namespace std;
class Fruit?????????????? //定義一個類,名字叫Fruit
{
????????????
?string name;???? //定義一個name成員??????????
?string colour;?? //定義一個colour成員
public:?
?void print()????????????? //定義一個輸出名字的成員print()
?{
? cout<<colour<<" "<<name<<endl;
?}
?Fruit(const string &nst,const string &cst = "green"):name(nst),colour(cst)? //構造函數(shù)
?{
?name +="s";
?}
?Fruit(istream &is = cin)?? //新的構造函數(shù)
?{
? is>>colour>>name;
?}
};
int main()
{
?Fruit apple("apple");? //定義一個Fruit類對象apple
?Fruit apple2;
?apple.print();
?apple2.print();
??
?return 0;
}

發(fā)現(xiàn)我重載的默認構造函數(shù)沒有?這次利用的是默認形參(istream &is =cin),學過io的就應該知道,他的意思表示,默認就是從標準設備輸入(如鍵盤)。你運行下,就知道怎么回事了。現(xiàn)在我們講一個新內容,復制構造函數(shù),什么意思?先看下面的例子。

例6.1:

#include <string>
#include <iostream>
using namespace std;
class Fruit?????????????? //定義一個類,名字叫Fruit
{
????????????
?string name;???? //定義一個name成員??????????
?string colour;?? //定義一個colour成員
public:?
?void print()????????????? //定義一個輸出名字的成員print()
?{
? cout<<colour<<" "<<name<<endl;
?}
?Fruit(const string &nst,const string &cst = "green"):name(nst),colour(cst)? //構造函數(shù)
?{
?name +="s";
?}
?Fruit(){}
};
int main()
{
?Fruit apple("apple");? //定義一個Fruit類對象apple
?Fruit apple2(apple);//發(fā)現(xiàn)這里有什么問題沒有?
?apple.print();
?apple2.print();
??? return 0;
}

你會發(fā)現(xiàn)apple2也輸出了green apples,為什么啊?(apple)和("apple")一樣?你這這樣理解可就錯了,肯定不一樣嘛。但是當我們使用Fruit apple2(apple);的時候調用了哪個構造函數(shù)呢?我們沒有定義一個類似的構造函數(shù)啊?按道理應該編譯失敗,不是嗎?恩,這里調用的構造函數(shù)就叫做復制構造函數(shù),即用一個同樣類型的對象構造另一個對象的構造函數(shù),不過在這里,我們沒有定義,所以由系統(tǒng)幫我們自動定義的,叫做默認復制構造函數(shù)。效果自然就是復制一下。你把第一個對象改成apple3你就會發(fā)現(xiàn),apple2沒有辦法定義了,因為它調用的是復制Fruit對象apple的構造函數(shù),而不是用字符串"apple"那個構造函數(shù)。C++ Primer這樣定義復制構造函數(shù),我引用一下“只有單個形參,而且該形參是對本類類型對象的引用(常用const修飾)”。我們來看看系統(tǒng)合成的默認復制構造函數(shù)的一個有趣應用:

例6.2:

#include <iostream>
using namespace std;
class Aint
{
public:
?int aival[3];
};
int main()
{
?Aint as={1,2,3};
?cout<<as.aival[0]<<as.aival[1]<<as.aival[2]<<endl;
?Aint bs(as);
?cout<<bs.aival[0]<<bs.aival[1]<<bs.aival[2]<<endl;
?return 0;
}

很簡單的例子吧,不過也很有趣,我們都知道,數(shù)組是沒有辦法通過等于來復制的,要復制只能利用循環(huán)遍歷,我們自己定義了一個只包含整形數(shù)組的類,而當我們利用系統(tǒng)合成的默認復制構造函數(shù)的時候實現(xiàn)了數(shù)組的復制,注意,是一次性等于復制。呵呵。這也說明了一個問題,就是系統(tǒng)的默認復制構造函數(shù)在對付數(shù)組時,幫我們遍歷復制了。現(xiàn)在我們自己定義一個復制構造函數(shù)。要說明的是,一般情況下系統(tǒng)定義的復制構造函數(shù)已經夠用了,當你自己要定義的時候是想實現(xiàn)不同的功能,比如更好的處理指針的復制等,下面的例子只是看看用法,我也只講用法而不講究有沒有實際意義。

例6.3:

#include <string>
#include <iostream>
using namespace std;
class Fruit?????????????? //定義一個類,名字叫Fruit
{
?string name;???? //定義一個name成員??????????
?string colour;?? //定義一個colour成員
public:
?void print()????????????? //定義一個輸出名字的成員print()
?{
??cout<<colour<<" "<<name<<endl;
?}
?Fruit(const string &nst = "apple",const string &cst = "green"):name(nst),colour(cst){}? //構造函數(shù)
?Fruit(Fruit &aF):name(aF.name),colour(aF.colour)??????????? //這是我們自己定義的復制構造函數(shù)
?{
??name +="s";??????????????? //讓他和默認的不同
?}
};

int main()
{
?Fruit apple;? //定義一個Fruit類對象apple
?Fruit apple2(apple);//調用的是我們自己定義的復制構造函數(shù)

?apple.print();
?apple2.print();????????? //你會發(fā)現(xiàn)輸出多了個's'
?return 0;

}

這里你會看到我們自己定義的復制構造函數(shù)的作用,直觀的看到apple只輸出green apple,而apple2輸出green aples,要說明的是,這也是復制構造函數(shù)也是構造函數(shù),也可以用初始化列表,而且在C++ Primer中還推薦你使用初始化列表。下面我們看看,假如你向讓你的類禁止復制怎么辦啊?很簡單,讓你的復制構造函數(shù)跑到private里面去,這時候友元和成員還可以使用復制,那你就光聲明一個復制構造函數(shù),但是,你不定義它,在C++里面,光聲明不定義一個成員函數(shù)是合法的,但是,使用的話就會導致編譯失敗了,(普通函數(shù)也是這樣)通過這種手段,你就能禁止一切復制的發(fā)生了(其實是發(fā)現(xiàn)一切本需要復制構造函數(shù)的地方了)。見下例。

例6.4:

#include <string>
#include <iostream>
using namespace std;
class Fruit?????????????? //定義一個類,名字叫Fruit
{
?string name;???? //定義一個name成員??????????
?string colour;?? //定義一個colour成員
public:
?void print()????????????? //定義一個輸出名字的成員print()
?{
??cout<<colour<<" "<<name<<endl;
?}
?Fruit(const string &nst = "apple",const string &cst = "green"):name(nst),colour(cst)
?{}? //構造函數(shù)
private:
?Fruit(Fruit &aF);??????? //把它定義在private下
};
int main()
{
?Fruit apple("apple");? //定義一個Fruit類對象apple
//?Fruit apple2(apple);?? //你這樣的嘗試會導致編譯失敗的,cannot access private 錯誤??
?apple.print();
?return 0;
}

在犯了一個我半天也沒有發(fā)現(xiàn)的錯誤的后,我發(fā)現(xiàn)了,當利用形如Fruit apple2 = apple方式來定義并初始化一個對象的時候,調用的也是復制構造函數(shù),詳情請見那個帖子《警惕!C++里面“=”不一定就是等于(賦值)。

總結

以上是生活随笔為你收集整理的浅谈C++类(6)--复制构造函数的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。