最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網 會員登陸 & 注冊

C++拷貝構造器、運算符重載1

2023-09-08 06:58 作者:虛云幻仙  | 我要投稿

#include <iostream>

using namespace std;


class Str //模仿string類

{

????public:

???? Str(const char* ptr="") //接收字符串來初始化對象,不修改參數所以const,用默認參數來兼容無參構造器(無參生成空字符串)

???? {

???????? arr = new char[strlen(ptr) + 1]; //創(chuàng)建和參數長度一樣大的空間,動態(tài)分配的內存位于堆中

???????? strcpy(arr, ptr); //字符串賦值

???? }

???? ~Str()

???? {

???? ????delete[] arr; //釋放堆中的數組

???? }

???? Str(const Str& another) //拷貝構造器,使用一個已存在的對象初始化新的對象,默認生成,會將形參的所有字段拷貝用來初始化,格式固定: 類名(const 類名& 引用名),使用了引用,another就是主調函數中的實參對象本身

???? {

???????? //如果不手動定義拷貝構造器,默認生成的拷貝構造器會對所有字段進行成員賦值(淺拷貝),執(zhí)行arr=another.arr,這對基礎類型以及結構不會產生問題,但指針賦值會使兩個對象使用同一塊動態(tài)內存空間

???????? arr = new char[strlen(another.arr) + 1]; //在類的函數中不僅可以調用當前對象的私有字段,也可以調用其他同類型對象的私有字段,對象中有指針字段時需要重寫拷貝構造器

???????? strcpy(this->arr, another.arr); //過程和使用字符串初始化類似,this是指向當前對象的指針,*this就是當前Str對象(的別名),直接調用arr就相當于(*this).arr

???????? cout << "copy" << endl;

???? }

???? Str& operator=(const Str& another) //賦值運算符重載,將一個存在的對象賦值給一個存在的對象,默認生成,和默認的拷貝構造器一樣執(zhí)行成員賦值,只拷貝字段不創(chuàng)建額外生成的動態(tài)內存空間,固定格式: 類名& operator=(const 類名& 引用名),返回當前對象的引用

???? {

???????? if (this == &another) //this為指向當前對象的指針,another為另一個對象的引用即另一個Str本身,判斷當前對象的地址(this的值)和另一個對象的地址(&another)相同即自己賦值自己,直接返回

???????? ???? return *this; //*this為當前對象,將當前對象的引用返回,不能返回another因為聲明const

???????? delete[]arr; //先釋放已創(chuàng)建的內存

???????? arr = new char[strlen(another.arr) + 1];

???????? strcpy(this->arr, another.arr); //和上面的構造方法相同

???????? cout << "overload" << endl;

???? }

???? //構造器、析構器、拷貝構造器、賦值運算符重載、地址運算符重載(C++11增加移動構造器、移動賦值運算符重載),這五個函數在沒有手動定義的情況下會默認生成;默認的地址運算符重載會返回對象所在的地址

???? const char* c_str()

???? {

???? ????return arr; //將私有的數組指針返回并聲明const禁止修改

???? }

???? size_t find(char ch)

???? {

???????? char* ptr = strchr(arr, ch);

???????? return ptr ? ptr - arr : (size_t)-1;

???? }

???? Str operator+(const Str& another) //模擬字符串相加,s1+s2返回一個新的字符串,內容為s1拼接s2

???? {

???????? Str res; //生成新的對象

???????? res.~Str(); //釋放無參構造器生成的char[1]數組

???????? res.arr = new char[strlen(this->arr)+strlen(another.arr) + 1]; //兩個對象字符串長度之和,留一個\0

???????? strcpy(res.arr, this->arr); //先拷貝this

???????? strcat(res.arr, another.arr); //使用strcat拼接

???????? return res; //res對象是自動變量,在返回后釋放,所以不能返回res的引用,返回操作實際執(zhí)行了一次拷貝構造器,在函數外(具體位置取決于實現)用res初始化了一個臨時空間交給主調函數

???? }

???? bool operator>(const Str& another) //通過strcmp實現對象的比較

???? {

???? ????return strcmp(arr, another.arr) > 0;

???? }

???? bool operator<(const Str& another)

???? {

???? ????return strcmp(arr, another.arr) < 0;

???? }

???? bool operator==(const Str& another) //三種運算符分別重載

???? {

???? ????return strcmp(arr, another.arr) == 0;

???? }

???? char& operator[](int index) //實現對象s1[i]取元素

???? {

???????? return arr[index]; //返回元素本身可修改,就像char數組[i]一樣使用

????????//注意這里的返回類型為char&,如果是char則返回字符的備份,備份無法修改不能改變下標的字符,

???? }

???? char operator[](int index)const //const成員函數,如果調用對象為const時就不能返回下標字符本身因為可能會被修改,所以去掉&變成按值傳遞,返回char的值/下標字符的備份,格式為:函數頭 const {函數體},后續(xù)詳細介紹

???? {

???? ????return arr[index]; //返回的內容沒有變化,區(qū)別只在返回值和const

???? }

????private:

???? char* arr;

};


int mainclass2()

{

???? Str s,s1("s1"),s2("s2");

???? cout << s1.c_str() << endl;

???? cout << s1.find('1') << endl;

???? Str s3(s1); //拷貝構造器

???? Str s4 = s2; //也是拷貝構造器,聲明階段初始化值,和賦值不同

???? cout << s4.c_str() << endl;

???? Str s5;

???? s5 = s3; //賦值,相當于s5.operator=(s3)

???? s1 + s2; //s1+s2相當于s1.operator+(s2),返回結果是匿名空間,在c++代碼層面無法訪問這個沒有標識符的空間

???? Str s6 = s1 + s2;//將返回的空間標識為s6,所以過程中發(fā)生了一次無參構造、一次拷貝構造

???? cout << s6.c_str() << endl;

???? Str s7;

???? s7 = s3 + s4; //相當于s7.operator=(s3.operator+(s4)),運算符重載遵循運算符的優(yōu)先級

???? Str sarr[10] = { Str("ele1"),Str("ele2") }; //對象數組,和普通數組初始化一樣用{},如果初始化的項數小于數組大小,剩下的元素會調用無參構造器,所以聲明對象時應保留無參構造器

???? return 0;

}


Str returnclass()

{

???? return Str("匿名對象"); //先通過有參構造器創(chuàng)建對象,在函數return該對象時就會發(fā)生拷貝構造,將返回的對象作為拷貝構造器的參數,在臨時空間使用拷貝構造創(chuàng)建臨時對象,之后被調函數結束,自動變量釋放,主調函數訪問臨時空間

???? //和返回基本數據類型同理,return 1是返回1的備份,return 對象 是返回對象的備份,通過拷貝構造器創(chuàng)建備份

}


class ClassNoCopy

{

????public:

???? ClassNoCopy() {}

????private:

???? ClassNoCopy(const ClassNoCopy& another) {} //將拷貝構造器私有,禁止外部調用,手動聲明后不會再默認生成公有的拷貝構造器

???? ClassNoCopy& operator=(const ClassNoCopy& another)?= delete; //使用delete關鍵字禁用該成員函數,格式:任意成員函數的函數頭 = delete,當主調函數調用這個成員函數時會報錯

???? int val;

};

ClassNoCopy funcCNC()

{

ClassNoCopy c1;

//報錯:ClassNoCopy c2(c1); //拷貝構造器私有不可訪問

//報錯:ClassNoCopy c3 = c1; //聲明時初始化同樣調用拷貝構造器,私有不可訪問

ClassNoCopy c4;

//報錯:c4 = c1; //將一個對象賦值給另一個對象,賦值運算符重載不可訪問

//報錯:return c1; //返回對象調用拷貝構造器,私有不可訪問

}


class ClassOperatorOverload

{

????public:

???? int data;

???? ClassOperatorOverload(int val = 0)

???? {

???? ????data = val;

???? }

???? //ClassOperatorOverload& operator=(const ClassOperatorOverload& another)

???? //{

???????? // /*省略自己賦值自己的判斷*/

???????? // data = another.data;

???????? // return *this; //返回當前對象本身,可以實現鏈式賦值 c1 = c2 = c3 將c3賦值給c2后返回c2,再將c2賦值給c1(等號結合律右到左)。也支持(c1 =c2)=c3 將c2賦給c1返回c1,再將c3賦給c1返回c1

???? //}

???? //const ClassOperatorOverload& operator=(const ClassOperatorOverload& another) //將返回聲明為const,禁止將返回值作為左值,表達式 c1 = c2 = c3 仍然正常執(zhí)行(=運算符從右向左執(zhí)行),但(c1=c2)=c3報錯,因為c1=c2返回的c1的引用為const引用

???? //{

???????? // /*省略自己賦值自己的判斷*/

???????? // data = another.data;

???????? // return *this;

???? //}

???? void operator=(const ClassOperatorOverload& another) //不返回對象,這時c1=c2正常,c1=c2=c3報錯因為c2=c3無返回,而只改變返回值類型不構成重載,但都視為賦值運算符的函數,不再生成默認的

???? {

???????? // /*省略自己賦值自己的判斷*/

???????? data = another.data;

???? }

};


C++拷貝構造器、運算符重載1的評論 (共 條)

分享到微博請遵守國家法律
壶关县| 米易县| 同江市| 哈巴河县| 清流县| 浦江县| 陕西省| 沙洋县| 东光县| 保定市| 深泽县| 大丰市| 哈密市| 精河县| 潍坊市| 阳信县| 黄大仙区| 茶陵县| 双流县| 清苑县| 博乐市| 巴彦淖尔市| 裕民县| 台南县| 化德县| 萨迦县| 会昌县| 彰化市| 延安市| 隆昌县| 民权县| 化德县| 阿图什市| 抚顺县| 屏山县| 崇仁县| 富源县| 清徐县| 轮台县| 沙洋县| 普格县|