欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

【C++】類和對象(中)-創(chuàng)新互聯(lián)

文章目錄
  • 1.類的6個默認(rèn)成員函數(shù)
  • 2. 構(gòu)造函數(shù)
    • 2.1概念與特征
    • 2.2特征分析
  • 3.析構(gòu)函數(shù)
    • 3.1概念與特征
    • 3.2特征分析
  • 4.拷貝構(gòu)造函數(shù)
    • 4.1概念與特征
    • 4.2特征分析
  • 5.運算符重載
    • 5.1運算符重載的概念
    • 5.2賦值運算符重載
      • 5.2.1特性
      • 5.2.2特性分析
  • 6.const成員&&取地址及const取地址操作符重載
    • 6.1const成員
    • 6.2取地址及const取地址操作符重載
  • 7、總結(jié)

青岡網(wǎng)站制作公司哪家好,找創(chuàng)新互聯(lián)!從網(wǎng)頁設(shè)計、網(wǎng)站建設(shè)、微信開發(fā)、APP開發(fā)、成都響應(yīng)式網(wǎng)站建設(shè)公司等網(wǎng)站項目制作,到程序開發(fā),運營維護(hù)。創(chuàng)新互聯(lián)自2013年起到現(xiàn)在10年的時間,我們擁有了豐富的建站經(jīng)驗和運維經(jīng)驗,來保證我們的工作的順利進(jìn)行。專注于網(wǎng)站建設(shè)就選創(chuàng)新互聯(lián)。
1.類的6個默認(rèn)成員函數(shù)

如果一個類中沒有任何成員,那么我們把它稱為空類??疹愔幸矔詣由?個默認(rèn)成員函數(shù)。

默認(rèn)成員函數(shù):用戶沒有顯式實現(xiàn),編譯器會生成的成員函數(shù)稱為默認(rèn)成員函數(shù)。

image-20221024145647391

接下來我們詳細(xì)介紹一下這幾個默認(rèn)成員函數(shù)

2. 構(gòu)造函數(shù) 2.1概念與特征

在C語言實現(xiàn)的數(shù)據(jù)結(jié)構(gòu)中,下面以棧(Stack)為例,我們實現(xiàn)過StackInit這個接口,用于對棧進(jìn)行初始化,但是我們在使用棧的時候會經(jīng)常忘記調(diào)用這個函數(shù)對棧初始化,C++為了解決這個問題,就創(chuàng)建了一個叫做構(gòu)造函數(shù)的默認(rèn)成員函數(shù),用來對類進(jìn)行初始化。而且它會在類實例化的時候自動調(diào)用,這就完美解決了我們忘記調(diào)用的問題。

這里需要注意的是,構(gòu)造函數(shù)雖然名稱叫構(gòu)造,但是構(gòu)造函數(shù)的主要任務(wù)并不是開空間創(chuàng)建對象,而是初始化對象。

其特征如下:

  1. 函數(shù)名與類名相同。

  2. 無返回值。

  3. 對象實例化時編譯器自動調(diào)用對應(yīng)的構(gòu)造函數(shù)。

  4. 構(gòu)造函數(shù)可以重載和缺省參數(shù)。

  5. 如果類中沒有顯式定義構(gòu)造函數(shù),則C++編譯器會自動生成一個無參的默認(rèn)構(gòu)造函數(shù),一旦用戶顯式定義編譯器將不再生成。

  6. 編譯器自動生成的構(gòu)造函數(shù)對于內(nèi)置類型不做任何處理,對于自定義類型調(diào)用其默認(rèn)構(gòu)造函數(shù)。

  7. 無參的構(gòu)造函數(shù)、全缺省的構(gòu)造函數(shù)和編譯器默認(rèn)生成的構(gòu)造函數(shù)都稱為默認(rèn)構(gòu)造函數(shù),并且默認(rèn)構(gòu)造函數(shù)只能有1個。

    總結(jié):不傳參數(shù)就可以調(diào)用的構(gòu)造函數(shù),就叫默認(rèn)構(gòu)造函數(shù)

2.2特征分析

下面我們以Date類為例:

class Date
{public:
	Date(int year = 1970, int month = 1, int day = 1)//構(gòu)造函數(shù)
	{_year = year;
		_month = month;
		_day = day;
	}
	void Print()
	{cout<< _year<< '/'<< _month<< '/'<< _day<< endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{Date d1;
	d1.Print();
	return 0;
}

在定義構(gòu)造函數(shù)的時候,函數(shù)名與類名相同(特征1),并且沒有返回值(特征2),上述代碼運行的結(jié)果如下:

image-20221027195228167

顯然我們并沒有初始化d1,但是輸出的d1結(jié)果是已經(jīng)被初始化完成的,所以在實例化d1的時候就已經(jīng)自動調(diào)用了構(gòu)造函數(shù)。(特征3)

class Date
{public:
	Date(int year, int month = 1, int day = 1)//構(gòu)造函數(shù)
	{_year = year;
		_month = month;
		_day = day;
	}
	Date()//構(gòu)造函數(shù)重載
	{_year = 1970;
		_month = 1;
		_day = 1;
	}
	void Print()
	{cout<< _year<< '/'<< _month<< '/'<< _day<< endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{Date d1;
	Date d2(2022);
	d1.Print();
	d2.Print();
	return 0;
}

在上述代碼構(gòu)造函數(shù)的參數(shù)中可以看到我們給出了缺省值,調(diào)用的時候程序可以正常運行,可見構(gòu)造函數(shù)可以給出缺省值,并且兩個構(gòu)造函數(shù)無參和帶參構(gòu)成函數(shù)重載(特征4)

這里注意一下,無參和帶參全缺省的構(gòu)造函數(shù)不能同時出現(xiàn),雖然語法上沒有問題,但是在調(diào)用的時候會產(chǎn)生二義性,出現(xiàn)調(diào)用不明確的問題。

在類中如果需要自己實現(xiàn)構(gòu)造函數(shù)的話,一般推薦實現(xiàn)一個全缺省的構(gòu)造函數(shù)即可,防止出現(xiàn)冗余

image-20221027204831075

按照上述的特性5,如果在類中我們沒有實現(xiàn)構(gòu)造函數(shù),那么編譯器會自動給我們生成一個無參的構(gòu)造函數(shù),但是上圖中可以看到,似乎編譯器自動生成的構(gòu)造函數(shù)并沒有什么用,原因在特性6已經(jīng)說明:編譯器自動生成的構(gòu)造函數(shù)并不能對內(nèi)置類型進(jìn)行操作,對于自定義的類型,會調(diào)用它的默認(rèn)構(gòu)造函數(shù)。

注意:在C++11中針對內(nèi)置類型成員不初始化的缺陷,又打了補丁,即:內(nèi)置類型成員變量在類中聲明時可以給默認(rèn)值

image-20221027205526243

無參構(gòu)造函數(shù)、全缺省構(gòu)造函數(shù)、我們沒寫編譯器默認(rèn)生成的構(gòu)造函數(shù),都可以認(rèn)為是默認(rèn)構(gòu)造函數(shù),由于默認(rèn)構(gòu)造函數(shù)時無參的,所以如果出現(xiàn)多于一個的情況,那么調(diào)用的時候就會出現(xiàn)二義性,因此,只能存在一個默認(rèn)構(gòu)造函數(shù)**(特性7)**。

3.析構(gòu)函數(shù) 3.1概念與特征

上面我們介紹了構(gòu)造函數(shù),它是對標(biāo)C語言實現(xiàn)的棧中的StackInit,析構(gòu)函數(shù)對標(biāo)的就是StackDestory。那么相對應(yīng)的,析構(gòu)函數(shù)的任務(wù)不是銷毀對象,而是完成對象中的資源清理工作。

析構(gòu)函數(shù)的特征如下:

  1. 析構(gòu)函數(shù)名是在類名前加上字符 ~。
  2. 無參數(shù)無返回值類型。
  3. 一個類只能有一個析構(gòu)函數(shù)。若未顯式定義,系統(tǒng)會自動生成默認(rèn)的析構(gòu)函數(shù)。(析構(gòu)函數(shù)不能重載)
  4. 對象生命周期結(jié)束時,C++編譯器自動調(diào)用析構(gòu)函數(shù)。
  5. 編譯器生成的默認(rèn)析構(gòu)函數(shù),對自定類型成員調(diào)用它的析構(gòu)函數(shù),對內(nèi)置類型不做操作
  6. 如果類中沒有申請資源時,析構(gòu)函數(shù)可以不寫,直接使用編譯器生成的默認(rèn)析構(gòu)函數(shù),比如Date類;有資源申請時,一定要寫,否則會造成資源泄漏,比如Stack類。
3.2特征分析

下面我們以Stack類為例:

class Stack
{public:
	Stack(int capacity = 4)
	{_a = (int*)malloc(sizeof(int) * capacity);
		if (_a == nullptr)
		{	perror("malloc fail");
			exit(-1);
		}
		_top = 0;
		_capacity = capacity;
	}
	~Stack()
	{free(_a);
		_a = nullptr;
		_top = _capacity = 0;
	}
  	void Push(int x)
	{//...
	}
private:
	int* _a;
	int _top;
	int _capacity;
};

在定義析構(gòu)函數(shù)的時候,函數(shù)名函數(shù)名是在類名前加上字符 ~(特征1),并且沒有參數(shù)和返回值(特征2)。

基于上述的Stack類,我們定義一個MyQueue類:

class MyQueue
{public:
	void Push(int x)
	{_pushST.Push(x);
	}
private:
	Stack _pushST;
	Stack _popST;
};

image-20221107205835813

運行上述代碼,發(fā)現(xiàn)結(jié)果中輸出了構(gòu)造函數(shù)和析構(gòu)函數(shù)的函數(shù)名,證明在代碼運行的過程中自動調(diào)用了構(gòu)造函數(shù)和析構(gòu)函數(shù)(特征4)

image-20221107210421467

運行上述代碼,我們可以看到調(diào)用了兩次Stack的構(gòu)造函數(shù)和析構(gòu)函數(shù),所以對于MyQueue中的Stack的成員,編譯器會自動調(diào)用他的析構(gòu)函數(shù)(特性5)

4.拷貝構(gòu)造函數(shù) 4.1概念與特征

在定義內(nèi)置類型的時候,我們有時候會使用類似int a = b這樣的語句,這就是一種拷貝,對于自定義類型,我們可以直接拷貝,這種拷貝我們把它叫做淺拷貝,還有一種拷貝叫做深拷貝,深拷貝就是創(chuàng)建一個新的對象和數(shù)組,將原對象的各項屬性的“值”(數(shù)組的所有元素)拷貝過來,是“值”而不是“引用”。

我們在實例化一個新的對象的時候,經(jīng)??赡軙龅竭@種我們想拷貝已有對象的數(shù)據(jù),這時候會用到深拷貝,所以引入了拷貝構(gòu)造函數(shù)的概念。

拷貝構(gòu)造函數(shù):只有單個形參,該形參是對本類類型對象的引用(一般常用const修飾),在用已存在的類類型對象創(chuàng)建新對象時由編譯器自動調(diào)用。

拷貝構(gòu)造的特征:

  1. 拷貝構(gòu)造函數(shù)是構(gòu)造函數(shù)的一個重載形式。

  2. 拷貝構(gòu)造函數(shù)的參數(shù)只有一個且必須是類類型對象的引用,使用傳值方式編譯器直接報錯,因為會引發(fā)無窮遞歸調(diào)用。

  3. 若未顯式定義,編譯器會生成默認(rèn)的拷貝構(gòu)造函數(shù)。 默認(rèn)的拷貝構(gòu)造函數(shù)對象按內(nèi)存存儲按字節(jié)序完成拷貝,這種拷貝叫做淺拷貝,或者值拷貝。

  4. 編譯器自動生成的默認(rèn)拷貝構(gòu)造函數(shù)中,內(nèi)置類型是按照字節(jié)方式直接拷貝的,而自定義類型是調(diào)用其拷貝構(gòu)造函數(shù)完成拷貝的

    總結(jié):類中如果沒有涉及資源申請時,拷貝構(gòu)造函數(shù)是否寫都可以;一旦涉及到資源申請時,則拷貝構(gòu)造函數(shù)是一定要寫的,否則就是淺拷貝。

  5. 拷貝構(gòu)造函數(shù)典型調(diào)用場景:

    • 使用已存在對象創(chuàng)建新對象

    • 函數(shù)參數(shù)類型為類類型對象

    • 函數(shù)返回值類型為類類型對象

4.2特征分析

以date類為例

class date
{public:
	void print()
	{cout<< _year<< '/'<< _month<< '/'<< _day<< endl;
	}
	date(int year = 1970, int month = 1, int day = 1)
	{_year = year;
		_month = month;
		_day = day;
	}
	date(const date& d)
	{_year = d._year;
		_month = d._month;
		_day = d._day;
	}
private:
	int _year;
	int _month;
	int _day;
};

拷貝構(gòu)造函數(shù)是構(gòu)造函數(shù)的一個重載形式,拷貝構(gòu)造的函數(shù)參數(shù)與構(gòu)造函數(shù)不同**(特性1),由于我們對被拷貝的對象不需要改變它的值,為了安全方面考慮,在參數(shù)列表中加上const。拷貝構(gòu)造的參數(shù)類型是類引用,否則就會引發(fā)無窮遞歸調(diào)用。(特性2)**

image-20221024163711721

5.運算符重載 5.1運算符重載的概念

在C++中,我們會定義很多個類并且實例化對象,然而我們自定義的這些類對于編譯器是陌生的,所以一些操作符對于自定義的類型無法識別,為了增強代碼的可讀性,C++引入了運算符重載的概念。

運算符重載是具有特殊函數(shù)名的函數(shù),也具有其返回值類型,函數(shù)名字以及參數(shù)列表,其返回值類型與參數(shù)列表與普通的函數(shù)類似。

函數(shù)名為:關(guān)鍵字operator后面接需要重載的運算符符號,例如需要重載+=,那么函數(shù)名就是"operator+=",

函數(shù)原型:**返回值類型 operator操作符(參數(shù)列表) **

注意

  • 不能通過連接其他符號來創(chuàng)建新的操作符:比如operator@

  • 重載操作符必須有一個類類型參數(shù)

  • 用于內(nèi)置類型的運算符,其含義不能改變,例如:內(nèi)置的整型+,不能改變其含義

  • 作為類成員函數(shù)重載時,其形參看起來比操作數(shù)數(shù)目少1,因為成員函數(shù)的第一個參數(shù)為隱藏的this

  • .*::sizeof?:.注意以上5個運算符不能重載。

以重載日期類的日期+天數(shù)為例:

Date類

class Date
{public:
	Date(int year = 1970, int month = 1, int day = 1)
	{_year = year;
		_month = month;
		_day = day;
	}
	//獲取每個月的天數(shù)
	int GetMonthDay(int year, int month)
	{static int day[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31 };
		if ((month == 2) && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))) //閏年
			return 29;
		return day[month];
	}
	//打印
	void Print()
	{cout<< _year<< "/"<< _month<< "/"<< _day<< endl;
	}

private:
	int _year;
	int _month;
	int _day;
};

重載:

void operator+=(Date& d, int day)
{d._day += day;
	while (d._day >GetMonthDay(d._year, d._month))
	{d._day -= GetMonthDay(d._year, d._month);
		d._month++;

		if (d._month >12)
		{	d._month -= 12;
			d._year++;
		}
	}
}

但是,在我們上手去寫的時候就會發(fā)現(xiàn),我們在類外面寫運算符重載的話,不能直接訪問類里面的private成員變量,所以我們推薦把運算符重載寫在類里面,由于類里面的成員函數(shù)的第一個參數(shù)都是隱藏的this指針,所以寫在類里面的運算符重載的參數(shù)通常會比運算符少一個操作數(shù),所以在類里面的日期+天數(shù)重載代碼為:

//運算符重載+=
void operator+=(int day)  //只傳遞右操作數(shù),通過this操作左操作數(shù)
{this->_day += day;  //這里的this->編譯器會自動添加
    while (_day >GetMonthDay(_year, _month))
    {_day -= GetMonthDay(_year, _month);
        _month++;

        if (_month >12)
        {_month -= 12;
            _year++;
        }
    }
}
5.2賦值運算符重載

賦值重載既是默認(rèn)成員函數(shù),又是運算符重載。

5.2.1特性
  1. 賦值重載的格式規(guī)范;
  2. 賦值運算符只能重載成類的成員函數(shù)不能重載成全局函數(shù);
  3. 若未顯式定義,編譯器會生成默認(rèn)的賦值重載函數(shù);
  4. 默認(rèn)的賦值重載函數(shù)對內(nèi)置類型以字節(jié)為單位直接進(jìn)行拷貝 – 淺拷貝,對自定義類型調(diào)用其自身的賦值重載函數(shù);
5.2.2特性分析

1.函數(shù)格式:

賦值重載函數(shù)的格式一般有如下要求:

使用引用做參數(shù),并以 const 修飾

我們知道,使用傳值傳參時函數(shù)形參是實參的一份臨時拷貝,所以傳值傳參會調(diào)用拷貝構(gòu)造函數(shù);而使用引用做參數(shù)時,形參是實參的別名,從而減少了調(diào)用拷貝構(gòu)造在時間和空間上的消耗;另外,賦值重載只會改變被賦值對象,而不會改變賦值對象,所以我們使用 const 來防止函數(shù)內(nèi)部的誤操作;

void operator=(const Date& d);

使用引用做返回值且返回值為*this

我們可以對內(nèi)置類型進(jìn)行連續(xù)賦值,比如int i,j; i = j = 0;那么對于自定義類型來說,我們也可以使用運算符重載來讓其支持連續(xù)賦值,則重載函數(shù)就必須具有返回值;同時,由于我們是在函數(shù)外部調(diào)用重載函數(shù),所以重載函數(shù)調(diào)用結(jié)束后該對象仍然存在,那么我們就可以使用引用作為函數(shù)的返回值,從而減少一次返回值的拷貝,提高程序效率;

另外,我們一般使用左操作數(shù)作為函數(shù)的返回值,也就是 this 指針指向的對象;

Date& operator=(const Date& d);

檢測是否自己給自己賦值

用戶在調(diào)用成員函數(shù)時有可能發(fā)生下面這種情況:Date d1; Date& d2 = d1; d1 = d2;這種情況對于只需要淺拷貝的對象來說并沒有什么大礙,但對于有資源申請,需要進(jìn)行深拷貝的對象來說就會發(fā)生不可控的事情,具體案例我們在后文中講解;

在 《Effective C++》中對賦值重載函數(shù)自我賦值的解釋是這樣的:
12227f6e1c1d88df383ecadc57e60e4c

2.重載為成員函數(shù):

賦值運算符只能重載成類的成員函數(shù)不能重載成全局函數(shù),這是因為賦值重載函數(shù)作為六個默認(rèn)成員函數(shù)之一,如果我們不顯示實現(xiàn),編譯器會默認(rèn)生成;此時用戶如果再在類外自己實現(xiàn)一個全局的賦值運算符重載,就會和編譯器在類中生成的默認(rèn)賦值運算符重載沖突,從而造成鏈接錯誤。

3.深淺拷貝:

賦值重載函數(shù)的特性和拷貝構(gòu)造函數(shù)非常類似 – 如果我們沒有顯式定義賦值重載,則編譯器會自動生成一個賦值重載,且自動生成的函數(shù)對內(nèi)置類型以字節(jié)為單位直接進(jìn)行拷貝,對自定義類型會去調(diào)用其自身的賦值重載函數(shù);所以對于沒有資源申請的類來說,我們不用自己去寫賦值重載函數(shù),直接使用默認(rèn)生成的即可,因為這種類只需要進(jìn)行淺拷貝 (值拷貝),比如 Date 類;而對于有資源申請的類來說,我們必須自己手動實現(xiàn)賦值重載函數(shù),來完成深拷貝工作;比如 Stack 類;

**注:**拷貝構(gòu)造函數(shù)完成的是初始化工作,在創(chuàng)建對象時自動調(diào)用;賦值重載完成的是已存在的對象之間的拷貝,需要手動調(diào)用;

**總結(jié):**自動生成的賦值重載函數(shù)對成員變量的處理規(guī)則和析構(gòu)函數(shù)一樣 – 對內(nèi)置類型以字節(jié)方式按值拷貝,對自定義類型調(diào)用其自身的賦值重載函數(shù);我們可以理解為:需要寫析構(gòu)函數(shù)的類就需要寫賦值重載函數(shù),不需要寫析構(gòu)函數(shù)的類就不需要寫賦值重載函數(shù);

6.const成員&&取地址及const取地址操作符重載 6.1const成員

我們看下面一個例子:

class date
{public:
	void print()
	{cout<< _year<< '/'<< _month<< '/'<< _day<< endl;
	}
    date(int year = 1970, int month = 1, int day = 1)
	{_year = year;
		_month = month;
		_day = day;
	}
	date(const date& d)
	{_year = d._year;
		_month = d._month;
		_day = d._day;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{date d1(2022,12,1);
    const date d2(d1);
    d1.print();
    d2.print();
    return 0;
}

這段代碼運行會報以下錯誤,原因是我們在調(diào)用d2.print()的時候默認(rèn)的this指針參數(shù)的了類型是date* const this,this指向的值是可修改的,但是實際上d2是const修飾的對象,所以會造成權(quán)限的放大。

image-20221221104655319

要解決這類問題的話,我們就需要把this的類型改為const date* const this,但是this指針是隱藏的,所以C++提供了一種新的方式,就是在函數(shù)參數(shù)的括號后面加const表示修飾*this的const。

void print() const

image-20221221105347175

6.2取地址及const取地址操作符重載

這兩個默認(rèn)成員函數(shù)一般不用重新定義 ,編譯器默認(rèn)會生成。如果一定要自己定義的話,那么代碼是這樣的:

class date
{public:
	date* operator&()
	{return this;
	}
	const date* operator&() const
	{return this;
	}
private:
	int _year;
	int _month;
	int _day;
};

這兩個運算符一般不需要重載,使用編譯器生成的默認(rèn)取地址的重載即可,只有特殊情況,才需要重載,比如想讓別人獲取到指定的內(nèi)容

7、總結(jié)

C++的類里面存在六個默認(rèn)成員函數(shù) – 構(gòu)造、析構(gòu)、拷貝構(gòu)造、賦值重載、取地址重載、const 取地址重載,其中前面四個函數(shù)非常重要,也非常復(fù)雜,需要我們根據(jù)具體情況判斷是否需要顯式定義,而最后兩個函數(shù)通常不需要顯示定義,使用編譯器默認(rèn)生成的即可;

1、構(gòu)造函數(shù)

  • 構(gòu)造函數(shù)完成對象的初始化工作,由編譯器在實例化對象時自動調(diào)用;
  • 默認(rèn)構(gòu)造函數(shù)是指不需要傳遞參數(shù)的構(gòu)造函數(shù),一共有三種 – 編譯器自動生成的、顯式定義且無參數(shù)的、顯式定義且全缺省的;
    如果用戶顯式定義了構(gòu)造函數(shù),那么編譯器會根據(jù)構(gòu)造函數(shù)的內(nèi)容進(jìn)行初始化,如果用戶沒有顯式定義,那么編譯器會調(diào)用默生成的構(gòu)造函數(shù);
  • 默認(rèn)生成的構(gòu)造函數(shù)對內(nèi)置類型不處理,對自定義類型會去調(diào)用自定義類型的默認(rèn)構(gòu)造;
  • 為了彌補構(gòu)造函數(shù)對內(nèi)置類型不處理的缺陷,C++11打了一個補丁 – 允許在成員變量聲明的地方給缺省值;如果構(gòu)造函數(shù)沒有對該變量進(jìn)行初始化,則該變量會被初始化為缺省值;
  • 構(gòu)造函數(shù)還存在一個初始化列表,初始化列表的存在有著非常大的意義;

2、析構(gòu)函數(shù)

  • 析構(gòu)函數(shù)完成對象中資源的清理工作,由編譯器在銷毀對象時自動調(diào)用;
  • 如果用戶顯式定義了析構(gòu)函數(shù),編譯器會根據(jù)析構(gòu)函數(shù)的內(nèi)容進(jìn)行析構(gòu);如果用戶沒有顯示定義,編譯器會調(diào)用默認(rèn)生成的析構(gòu)函數(shù);
  • 默認(rèn)生成的析構(gòu)函數(shù)對內(nèi)置類型不處理,對自定義類型會去調(diào)用自定義類型的析構(gòu)函數(shù);
  • 如果類中有資源的申請,比如動態(tài)開辟空間、打開文件,那么需要我們顯式定義析構(gòu)函數(shù);

3、拷貝構(gòu)造

  • 拷貝構(gòu)造函數(shù)是用一個已存在的對象去初始化另一個正在實例化的對象,由編譯器在實例化對象時自動調(diào)用;
  • 拷貝構(gòu)造的參數(shù)必須為引用類型,否則編譯器報錯 – 值傳遞會引發(fā)拷貝構(gòu)造函數(shù)的無窮遞歸;
  • 如果用戶顯式定義了拷貝構(gòu)造函數(shù),編譯器會根據(jù)拷貝構(gòu)造函數(shù)的內(nèi)容進(jìn)行拷貝;如果用戶沒有顯示定義,編譯器會調(diào)用默認(rèn)生成的拷貝構(gòu)造函數(shù);
  • 默認(rèn)生成的拷貝構(gòu)造函數(shù)對于內(nèi)置類型完成值拷貝 (淺拷貝),對于自定義類型會去調(diào)用自定義類型的拷貝構(gòu)造函數(shù);
  • 當(dāng)類里面有空間的動態(tài)開辟時,直接進(jìn)行值拷貝會讓兩個指針指向同一塊動態(tài)內(nèi)存,從而使得對象銷毀時對同一塊空間析構(gòu)兩次;所以這種情況下我們需要自己顯式定義拷貝構(gòu)造函數(shù)完成深拷貝;

4、運算符重載

  • 運算符重載是C++為了增強代碼的可讀性而引入的語法,它只能對自定義類型使用,其函數(shù)名為 operator 關(guān)鍵字加相關(guān)運算符;
  • 由于運算符重載函數(shù)通常都要訪問類的成員變量,所以我們一般將其定義為類的成員函數(shù);同時,因為類的成員函數(shù)的一個參數(shù)為隱藏的 this 指針,所以其看起來會少一個參數(shù);
  • 同一運算符的重載函數(shù)之間也可以構(gòu)成函數(shù)重載,比如 operator++ 與 operator++(int);

5、賦值重載

  • 賦值重載函數(shù)是將一個已存在對象中的數(shù)據(jù)賦值給另一個已存在的對象,注意不是初始化,需要自己顯示調(diào)用;它屬于運算符重載的一種;
  • 如果用戶顯式定義了賦值重載函數(shù),編譯器會根據(jù)賦值重載函數(shù)的內(nèi)容進(jìn)行賦值;如果用戶沒有顯示定義,編譯器會調(diào)用默認(rèn)生成的賦值重載函數(shù);
  • 默認(rèn)生成的賦值重載函數(shù)對于內(nèi)置類型完成值拷貝 (淺拷貝),對于自定義類型會去調(diào)用自定義類型的賦值重載函數(shù);
  • 賦值重載函數(shù)和拷貝構(gòu)造函數(shù)一樣,也存在著深淺拷貝的問題,且其與拷貝構(gòu)造函數(shù)不同的地方在于它還很有可能造成內(nèi)存泄漏;所以當(dāng)類中有空間的動態(tài)開辟時我們需要自己顯式定義賦值重載函數(shù)來釋放原空間以及完成深拷貝;
  • 為了提高函數(shù)效率與保護(hù)對象,通常使用引用作參數(shù),并加以 const 修飾;同時為了滿足連續(xù)賦值,通常使用引用作返回值,且一般返回左操作數(shù),即 *this;
  • 賦值重載函數(shù)必須定義為類的成員函數(shù),否則編譯器默認(rèn)生成的賦值重載會與類外自定義的賦值重載沖突;

6、const 成員函數(shù)

  • 由于指針和引用傳遞參數(shù)時存在權(quán)限的擴(kuò)大、縮小與平移的問題,所以 const 類型的對象不能調(diào)用成員函數(shù),因為成員函數(shù)的 this 指針默認(rèn)是非 const 的,二者之間傳參存在權(quán)限擴(kuò)大的問題;
  • 同時我們?yōu)榱颂岣吆瘮?shù)效率以及保護(hù)對象,一般都會將成員函數(shù)的第二個參數(shù)使用 const 修飾,這就導(dǎo)致了該對象在成員函數(shù)內(nèi)也不能調(diào)用其他成員函數(shù);
  • 為了解決這個問題,C++設(shè)計出了 const 成員函數(shù) – 在函數(shù)最后面添加 const 修飾,該 const 只修飾 this 指針,不修飾函數(shù)的其他參數(shù);
  • 所以如果我們在設(shè)計類時,只要成員函數(shù)不改變第一個對象,我們建議最后都使用 const 修飾;

7、取地址重載與 const 取地址重載

  • 取地址重載與 const 取地址重載是獲取一個對象/一個只讀對象的地址,需要自己顯式調(diào)用;它們屬于運算符重載,同時它們二者之間還構(gòu)成函數(shù)重載;
  • 大多數(shù)情況下我們都不會去顯示實現(xiàn)這兩個函數(shù),使用編譯器默認(rèn)生成的即可;只有極少數(shù)情況需要我們自己定義,比如防止用戶獲取到一個對象的地址;
    員函數(shù),否則編譯器默認(rèn)生成的賦值重載會與類外自定義的賦值重載沖突;

6、const 成員函數(shù)

  • 由于指針和引用傳遞參數(shù)時存在權(quán)限的擴(kuò)大、縮小與平移的問題,所以 const 類型的對象不能調(diào)用成員函數(shù),因為成員函數(shù)的 this 指針默認(rèn)是非 const 的,二者之間傳參存在權(quán)限擴(kuò)大的問題;
  • 同時我們?yōu)榱颂岣吆瘮?shù)效率以及保護(hù)對象,一般都會將成員函數(shù)的第二個參數(shù)使用 const 修飾,這就導(dǎo)致了該對象在成員函數(shù)內(nèi)也不能調(diào)用其他成員函數(shù);
  • 為了解決這個問題,C++設(shè)計出了 const 成員函數(shù) – 在函數(shù)最后面添加 const 修飾,該 const 只修飾 this 指針,不修飾函數(shù)的其他參數(shù);
  • 所以如果我們在設(shè)計類時,只要成員函數(shù)不改變第一個對象,我們建議最后都使用 const 修飾;

7、取地址重載與 const 取地址重載

  • 取地址重載與 const 取地址重載是獲取一個對象/一個只讀對象的地址,需要自己顯式調(diào)用;它們屬于運算符重載,同時它們二者之間還構(gòu)成函數(shù)重載;
  • 大多數(shù)情況下我們都不會去顯示實現(xiàn)這兩個函數(shù),使用編譯器默認(rèn)生成的即可;只有極少數(shù)情況需要我們自己定義,比如防止用戶獲取到一個對象的地址;

參考野豬佩奇大佬博客:大佬博客鏈接

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧

網(wǎng)頁標(biāo)題:【C++】類和對象(中)-創(chuàng)新互聯(lián)
當(dāng)前URL:http://chinadenli.net/article48/despep.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供企業(yè)網(wǎng)站制作、靜態(tài)網(wǎng)站定制網(wǎng)站、服務(wù)器托管微信公眾號、面包屑導(dǎo)航

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

小程序開發(fā)