国产精品天干天干,亚洲毛片在线,日韩gay小鲜肉啪啪18禁,女同Gay自慰喷水

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

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的評論 (共 條)

分享到微博請遵守國家法律
寿阳县| 白山市| 马鞍山市| 牙克石市| 雅江县| 汤原县| 桓仁| 石景山区| 紫云| 门源| 峨边| 米林县| 绥滨县| 四会市| 堆龙德庆县| 老河口市| 博乐市| 佛坪县| 太白县| 嘉义市| 于都县| 桃园市| 永城市| 益阳市| 临武县| 绥芬河市| 蒙阴县| 平阴县| 华容县| 永昌县| 阿巴嘎旗| 渭源县| 新泰市| 彭山县| 眉山市| 岢岚县| 闽侯县| 东莞市| 榆中县| 淄博市| 博野县|