国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

近萬(wàn)字的超詳細(xì)C++類(lèi)和對(duì)象,快進(jìn)來(lái)看看吧

這篇具有很好參考價(jià)值的文章主要介紹了近萬(wàn)字的超詳細(xì)C++類(lèi)和對(duì)象,快進(jìn)來(lái)看看吧。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

前情提要:
http://t.csdn.cn/Kqf6D

目錄

1.類(lèi)的6個(gè)默認(rèn)成員函數(shù)

1.1構(gòu)造函數(shù)

1.1.1?特性:

其特征如下:

1.1.2 初始化列表

注意:

1.1.3 explicit關(guān)鍵字

舉例:

1.2析構(gòu)函數(shù)

1.2.1 特性 :

析構(gòu)函數(shù)是特殊的成員函數(shù),

1.3?拷貝構(gòu)造函數(shù)

1.3.1概念:

1.3.2特征: 拷貝構(gòu)造函數(shù)也是特殊的成員函數(shù)

1.3.3特性如下:

1.4賦值運(yùn)算符重載

1.4.1運(yùn)算符重載的概念

1.4.2 賦值運(yùn)算符重載:

1. 賦值運(yùn)算符重載格式

2. 賦值運(yùn)算符只能重載成類(lèi)的成員函數(shù)不能重載成全局函數(shù)

3. 用戶(hù)沒(méi)有顯式實(shí)現(xiàn)時(shí)

1.4.3前置++和后置++重載

1.5 const成員

?編輯

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

2.初始化列表

3. static成員

3.1 概念:

3.2 特性

問(wèn)題:

4. 友元

4.1 友元函數(shù)?

友元函數(shù)的說(shuō)明

4.2 友元類(lèi)

注意:

代碼示例:

5. 內(nèi)部類(lèi)

特性:

6.拷貝對(duì)象時(shí)的一些編譯器優(yōu)化

6.1對(duì)象返回的總結(jié)

6.2函數(shù)傳參的總結(jié)

7.匿名對(duì)象

1.類(lèi)的6個(gè)默認(rèn)成員函數(shù)

如果一個(gè)類(lèi)中什么成員都沒(méi)有,簡(jiǎn)稱(chēng)為空類(lèi)。 任何類(lèi)在什么都不寫(xiě)時(shí),編譯器會(huì)自動(dòng)生成以下6個(gè)默認(rèn)成員函數(shù)。

默認(rèn)成員函數(shù):用戶(hù)沒(méi)有顯式實(shí)現(xiàn),編譯器會(huì)生成的成員函數(shù)稱(chēng)為默認(rèn)成員函數(shù)。

近萬(wàn)字的超詳細(xì)C++類(lèi)和對(duì)象,快進(jìn)來(lái)看看吧

1.1構(gòu)造函數(shù)

構(gòu)造函數(shù)是一個(gè)特殊的成員函數(shù),名字與類(lèi)名相同,創(chuàng)建類(lèi)類(lèi)型對(duì)象時(shí)由編譯器自動(dòng)調(diào)用,以保證 每個(gè)數(shù)據(jù)成員都有 一個(gè)合適的初始值,并且在對(duì)象整個(gè)生命周期內(nèi)只調(diào)用一次。

1.1.1?特性:

構(gòu)造函數(shù)是特殊的成員函數(shù),需要注意的是,構(gòu)造函數(shù)雖然名稱(chēng)叫構(gòu)造,但是構(gòu)造函數(shù)的主要任 務(wù)并不是開(kāi)空間創(chuàng)建對(duì)象,而是初始化對(duì)象。

其特征如下:

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

2. 無(wú)返回值。

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

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

class Date
 {
  public:
      // 1.無(wú)參構(gòu)造函數(shù)
      Date()
     {}
  
      // 2.帶參構(gòu)造函數(shù)
      Date(int year, int month, int day)
     {
          _year = year;
5. 如果類(lèi)中沒(méi)有顯式定義構(gòu)造函數(shù),則C++編譯器會(huì)自動(dòng)生成一個(gè)無(wú)參的默認(rèn)構(gòu)造函數(shù),一旦
用戶(hù)顯式定義編譯器將不再生成。
          _month = month;
          _day = day;
     }
  private:
      int _year;
      int _month;
      int _day;
 };
  
  void TestDate()
 {
      Date d1; // 調(diào)用無(wú)參構(gòu)造函數(shù)
      Date d2(2015, 1, 1); // 調(diào)用帶參的構(gòu)造函數(shù)
  
      // 注意:如果通過(guò)無(wú)參構(gòu)造函數(shù)創(chuàng)建對(duì)象時(shí),對(duì)象后面不用跟括號(hào),否則編譯器無(wú)法分析清楚函數(shù)聲明還是調(diào)用
      // 以下代碼的函數(shù):聲明了d3函數(shù),該函數(shù)無(wú)參,返回一個(gè)日期類(lèi)型的對(duì)象
      // warning C4930: “Date d3(void)”: 未調(diào)用原型函數(shù)(是否是有意用變量定義的?)
      Date d3();
}

? ? ? // 注意:如果通過(guò)無(wú)參構(gòu)造函數(shù)創(chuàng)建對(duì)象時(shí),對(duì)象后面不用跟括號(hào),否則編譯器無(wú)法分析清楚是函數(shù)聲明還是函數(shù)調(diào)用
? ? ? // 以下代碼的函數(shù):聲明了d3函數(shù),該函數(shù)無(wú)參,返回一個(gè)日期類(lèi)型的對(duì)象
? ? ? // warning C4930: “Date d3(void)”: 未調(diào)用原型函數(shù)(是否是有意用變量定義的?)
? ? ? Date d3();

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

6. 無(wú)參的構(gòu)造函數(shù)和全缺省的構(gòu)造函數(shù)都稱(chēng)為默認(rèn)構(gòu)造函數(shù),并且默認(rèn)構(gòu)造函數(shù)只能有一個(gè)。

注意:無(wú)參構(gòu)造函數(shù)、全缺省構(gòu)造函數(shù)、我們沒(méi)寫(xiě)編譯器默認(rèn)生成的構(gòu)造函數(shù),都可以認(rèn)為是默認(rèn)構(gòu)造函數(shù)。

7.編譯器生成的默認(rèn)構(gòu)造函數(shù)并沒(méi)有什么用?

C++把類(lèi)型分成內(nèi)置類(lèi)型(基本類(lèi)型)和自定義類(lèi)型。內(nèi)置類(lèi)型就是語(yǔ)言提供的數(shù)據(jù)類(lèi)型,如:int/char...,自定義類(lèi)型就是我們使用class/struct/union等自己定義的類(lèi)型,看看下面的程序,就會(huì)發(fā)現(xiàn)編譯器生成默認(rèn)的構(gòu)造函數(shù)會(huì)對(duì)自定類(lèi)型成員_t調(diào)用的它的默認(rèn)成員函數(shù)。

1.1.2 初始化列表

在創(chuàng)建對(duì)象時(shí),編譯器通過(guò)調(diào)用構(gòu)造函數(shù),給對(duì)象中各個(gè)成員變量一個(gè)合適的初始值。也就是雖然構(gòu)造函數(shù)調(diào)用之后,對(duì)象中已經(jīng)有了一個(gè)初始值,但是不能將其稱(chēng)為對(duì)對(duì)象中成員變量 的初始化,構(gòu)造函數(shù)體中的語(yǔ)句只能將其稱(chēng)為賦初值,而不能稱(chēng)作初始化。因?yàn)槌跏蓟荒艹跏?化一次,而構(gòu)造函數(shù)體內(nèi)可以多次賦值。

初始化列表:以一個(gè)冒號(hào)開(kāi)始,接著是一個(gè)以逗號(hào)分隔的數(shù)據(jù)成員列表,每個(gè)"成員變量"后面跟 一個(gè)放在括號(hào)中的初始值或表達(dá)式。

注意:

1. 每個(gè)成員變量在初始化列表中只能出現(xiàn)一次(初始化只能初始化一次)

2. 類(lèi)中包含以下成員,必須放在初始化列表位置進(jìn)行初始化:

引用成員變量

const成員變量

自定義類(lèi)型成員(且該類(lèi)沒(méi)有默認(rèn)構(gòu)造函數(shù)時(shí))

3. 盡量使用初始化列表初始化,因?yàn)椴还苣闶欠袷褂贸跏蓟斜恚瑢?duì)于自定義類(lèi)型成員變量, 一定會(huì)先使用初始化列表初始化。

4. 成員變量在類(lèi)中聲明次序就是其在初始化列表中的初始化順序,與其在初始化列表中的先后 次序無(wú)關(guān)

1.1.3 explicit關(guān)鍵字

構(gòu)造函數(shù)不僅可以構(gòu)造與初始化對(duì)象,對(duì)于單個(gè)參數(shù)或者除第一個(gè)參數(shù)無(wú)缺省值其余均有缺省值 的構(gòu)造函數(shù),還具有類(lèi)型轉(zhuǎn)換的作用。

用explicit修飾構(gòu)造函數(shù),將會(huì)禁止構(gòu)造函數(shù)的隱式轉(zhuǎn)換。

舉例:
 // 1. 單參構(gòu)造函數(shù),沒(méi)有使用explicit修飾,具有類(lèi)型轉(zhuǎn)換作用
 // explicit修飾構(gòu)造函數(shù),禁止類(lèi)型轉(zhuǎn)換---explicit去掉之后,代碼可以通過(guò)編譯
class Date {
public:
	//explicit Date(int year)
	//	:_year(year)
	//{}
	
	// 2. 雖然有多個(gè)參數(shù),但是創(chuàng)建對(duì)象時(shí)后兩個(gè)參數(shù)可以不傳遞,沒(méi)有使用explicit修飾,具
	//有類(lèi)型轉(zhuǎn)換作用
	//  explicit修飾構(gòu)造函數(shù),禁止類(lèi)型轉(zhuǎn)換
	 explicit Date(int year, int month = 1, int day = 1)
	 : _year(year)
	 , _month(month)
	 , _day(day)
	 {}
	 
	Date& operator=(const Date& d)
	{
		if (this != &d)
		{
			_year = d._year;
			_month = d._month;
			_day = d._day;
		}
		return *this;
	}
private:
	int _year;
	int _month;
	int _day;
};

void Test()
{
	Date d1(2022);
	Date d2(2023);
	Date d3(d2);
	// 用一個(gè)整形變量給日期類(lèi)型對(duì)象賦值
	// 實(shí)際編譯器背后會(huì)用2023構(gòu)造一個(gè)無(wú)名對(duì)象,最后用無(wú)名對(duì)象給d1對(duì)象進(jìn)行賦值
	d1 = 2023;
	// 將1屏蔽掉,2放開(kāi)時(shí)則編譯失敗,因?yàn)閑xplicit修飾構(gòu)造函數(shù),禁止了單參構(gòu)造函數(shù)類(lèi)型轉(zhuǎn)換的作用
}

int main()
{
	Test();
}

1.2析構(gòu)函數(shù)

? 析構(gòu)函數(shù)與構(gòu)造函數(shù)功能相反,析構(gòu)函數(shù)不是完成對(duì)對(duì)象本身的銷(xiāo)毀,局部對(duì)象銷(xiāo)毀工作是由 編譯器完成的。而對(duì)象在銷(xiāo)毀時(shí)會(huì)自動(dòng)調(diào)用析構(gòu)函數(shù),完成對(duì)象中資源的清理工作。

1.2.1 特性 :

析構(gòu)函數(shù)是特殊的成員函數(shù),

1.2.2其特征如下:

1. 析構(gòu)函數(shù)名是在類(lèi)名前加上字符 ~。

2. 無(wú)參數(shù)無(wú)返回值類(lèi)型。

3. 一個(gè)類(lèi)只能有一個(gè)析構(gòu)函數(shù)。若未顯式定義,系統(tǒng)會(huì)自動(dòng)生成默認(rèn)的析構(gòu)函數(shù)。注意:析構(gòu)函數(shù)不能重載

4. 對(duì)象生命周期結(jié)束時(shí),C++編譯系統(tǒng)系統(tǒng)自動(dòng)調(diào)用析構(gòu)函數(shù)。

5.?

內(nèi)置類(lèi)型成員:銷(xiāo)毀時(shí)不需要資源清理,最后系統(tǒng)直接將其內(nèi)存回收即可;

自定義類(lèi)型而:若一個(gè)類(lèi)的對(duì)象內(nèi)部也有對(duì)象,要將其內(nèi)部包含的類(lèi)的對(duì)象銷(xiāo)毀,所以要調(diào)用這個(gè)類(lèi)對(duì)應(yīng)的析構(gòu)函數(shù)。

6. 如果類(lèi)中沒(méi)有申請(qǐng)資源時(shí),析構(gòu)函數(shù)可以不寫(xiě),直接使用編譯器生成的默認(rèn)析構(gòu)函數(shù),比如 Date類(lèi);有資源申請(qǐng)時(shí),一定要寫(xiě),否則會(huì)造成資源泄漏,比如Stack類(lèi)。

1.3?拷貝構(gòu)造函數(shù)

1.3.1概念:

只有單個(gè)形參,該形參是對(duì)本類(lèi)類(lèi)型對(duì)象的引用(一般常用const修飾),在用已存在的類(lèi)類(lèi)型對(duì)象創(chuàng)建新對(duì)象時(shí)由編譯器自動(dòng)調(diào)用。

1.3.2特征: 拷貝構(gòu)造函數(shù)也是特殊的成員函數(shù)

1.3.3特性如下:

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

2. 拷貝構(gòu)造函數(shù)的參數(shù)只有一個(gè)且必須是類(lèi)類(lèi)型對(duì)象的引用,使用傳值方式編譯器直接報(bào)錯(cuò), 因?yàn)闀?huì)引發(fā)無(wú)窮遞歸調(diào)用。

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

#include<stdlib.h>
#include<iostream>

class Date
{
private:
    // 基本類(lèi)型(內(nèi)置類(lèi)型)
    int _year = 2023;
    int _month = 4;
    int _day = 4;
    // 自定義類(lèi)型
    Time _t;
};
class Time
{
public:
    Time()
    {
        _hour = 1;
        _minute = 1;
        _second = 1;
        //    注意:在編譯器生成的默認(rèn)拷貝構(gòu)造函數(shù)中,內(nèi)置類(lèi)型是按照字節(jié)方式直接拷貝的,而自定
        //    義類(lèi)型是調(diào)用其拷貝構(gòu)造函數(shù)完成拷貝的。
    }
    Time(const Time& t)
    {
        _hour = t._hour+1;
        _minute = t._minute+1;
        _second = t._second+1;
        std::cout << "Time::Time(const Time&)" << std::endl;
    }
private:
    int _hour;
    int _minute;
    int _second;
};

int main()
{
    Date d1;//構(gòu)造函數(shù)

    // 用已經(jīng)存在的d1拷貝構(gòu)造d2,此處會(huì)調(diào)用Date類(lèi)的拷貝構(gòu)造函數(shù)
    // 但Date類(lèi)并沒(méi)有顯式定義拷貝構(gòu)造函數(shù),則編譯器會(huì)給Date類(lèi)生成一個(gè)默認(rèn)的拷貝構(gòu)造函數(shù)
        Date d2(d1);
    return 0;
}

?其實(shí)此處Time生成的默認(rèn)拷貝構(gòu)造函數(shù)也是能使用的

class Time
{
public:
    Time()
    {
        _hour = 1;
        _minute = 1;
        _second = 1;
    }
    //Time(const Time& t)
    //{
    //    _hour = t._hour+1;
    //    _minute = t._minute+1;
    //    _second = t._second+1;
    //    std::cout << "Time::Time(const Time&)" << std::endl;
    //}
private:
    int _hour;
    int _minute;
    int _second;
};
class Date
{
private:
    // 基本類(lèi)型(內(nèi)置類(lèi)型)
    int _year = 2023;
    int _month = 4;
    int _day = 4;
    // 自定義類(lèi)型
    Time _t;
};
int main()
{
    Date d1;//構(gòu)造函數(shù)

    // 用已經(jīng)存在的d1拷貝構(gòu)造d2,此處會(huì)調(diào)用Date類(lèi)的拷貝構(gòu)造函數(shù)
    // 但Date類(lèi)并沒(méi)有顯式定義拷貝構(gòu)造函數(shù),則編譯器會(huì)給Date類(lèi)生成一個(gè)默認(rèn)的拷貝構(gòu)造函數(shù)
        Date d2(d1);
    return 0;
}

4.類(lèi)中如果沒(méi)有涉及資源申請(qǐng)時(shí),拷貝構(gòu)造函數(shù)是否寫(xiě)都可以;一旦涉及到資源申請(qǐng) 時(shí),則拷貝構(gòu)造函數(shù)是一定要寫(xiě)的,否則就是淺拷貝。

近萬(wàn)字的超詳細(xì)C++類(lèi)和對(duì)象,快進(jìn)來(lái)看看吧

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

1.使用已存在對(duì)象創(chuàng)建新對(duì)象

2.函數(shù)參數(shù)類(lèi)型為類(lèi)類(lèi)型對(duì)象

3.函數(shù)返回值類(lèi)型為類(lèi)類(lèi)型對(duì)象

近萬(wàn)字的超詳細(xì)C++類(lèi)和對(duì)象,快進(jìn)來(lái)看看吧

1.4賦值運(yùn)算符重載

1.4.1運(yùn)算符重載的概念

C++為了增強(qiáng)代碼的可讀性引入了運(yùn)算符重載,運(yùn)算符重載是具有特殊函數(shù)名的函數(shù),也具有其 返回值類(lèi)型,函數(shù)名字以及參數(shù)列表,其返回值類(lèi)型與參數(shù)列表與普通的函數(shù)類(lèi)似。 函數(shù)名字為:關(guān)鍵字operator后面接需要重載的運(yùn)算符符號(hào)。

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

運(yùn)算符重載成全局函數(shù),注意重載成全局函數(shù)時(shí)沒(méi)有this指針了,需要給兩個(gè)參數(shù)。

bool operator==(const Date& d1, const Date& d2)
{
    return d1._year == d2._year
   && d1._month == d2._month
        && d1._day == d2._day;
}

但是這是全局的operator==,如何保證其封裝性呢?

class Date
{ 
public:
 Date(int year = 1900, int month = 1, int day = 1)
   {
        _year = year;
        _month = month;
        _day = day;
   }
    
    // bool operator==(Date* this, const Date& d2)
    // 這里需要注意的是,左操作數(shù)是this,指向調(diào)用函數(shù)的對(duì)象
    bool operator==(const Date& d2)
 {
        return _year == d2._year;
            && _month == d2._month
            && _day == d2._day;
 }
private:
 int _year;
 int _month;
 int _day;
};

注意:

1.不能通過(guò)連接其他符號(hào)來(lái)創(chuàng)建新的操作符:比如operator@。

2.重載操作符必須有一個(gè)類(lèi)類(lèi)型參數(shù) 用于內(nèi)置類(lèi)型的運(yùn)算符,其含義不能改變。

例如:內(nèi)置的整型+,不能改變其含義作為類(lèi)成員函數(shù)重載時(shí),其形參看起來(lái)比操作數(shù)數(shù)目少1,因?yàn)槌蓡T函數(shù)的第一個(gè)參數(shù)為隱 藏的this? .*? ::? sizeof? ?:? . 注意以上5個(gè)運(yùn)算符不能重載。

1.4.2 賦值運(yùn)算符重載:

1. 賦值運(yùn)算符重載格式

參數(shù)類(lèi)型:const T&,傳遞引用可以提高傳參效率

返回值類(lèi)型:T&,返回引用可以提高返回的效率,有返回值目的是為了支持連續(xù)賦值

檢測(cè)是否自己給自己賦值:*this!=d1;

返回*this :要復(fù)合連續(xù)賦值的含義

2. 賦值運(yùn)算符只能重載成類(lèi)的成員函數(shù)不能重載成全局函數(shù)

原因:賦值運(yùn)算符如果不顯式實(shí)現(xiàn),編譯器會(huì)生成一個(gè)默認(rèn)的。此時(shí)用戶(hù)再在類(lèi)外自己實(shí)現(xiàn) 一個(gè)全局的賦值運(yùn)算符重載,就和編譯器在類(lèi)中生成的默認(rèn)賦值運(yùn)算符重載沖突了,故賦值 運(yùn)算符重載只能是類(lèi)的成員函數(shù)。

3. 用戶(hù)沒(méi)有顯式實(shí)現(xiàn)時(shí)

編譯器會(huì)生成一個(gè)默認(rèn)賦值運(yùn)算符重載,以值的方式逐字節(jié)拷貝。

注意:

1.內(nèi)置類(lèi)型成員變量是直接賦值的,而自定義類(lèi)型成員變量需要調(diào)用對(duì)應(yīng)類(lèi)的賦值運(yùn)算符重載完成賦值。

2.如果類(lèi)中未涉及到資源管理,賦值運(yùn)算符是否實(shí)現(xiàn)都可以;一旦涉及到資源管理則必須要實(shí)現(xiàn)。

近萬(wàn)字的超詳細(xì)C++類(lèi)和對(duì)象,快進(jìn)來(lái)看看吧

1.4.3前置++和后置++重載

1. 前置++:返回+1之后的結(jié)果
?注意:this指向的對(duì)象函數(shù)結(jié)束后不會(huì)銷(xiāo)毀,故以引用方式返回提高效率


 Date& operator++()
 {
 _day += 1;
 return *this;
 }

?2.后置++

前置++和后置++都是一元運(yùn)算符,為了讓前置++與后置++形成能正確重載

C++規(guī)定:后置++重載時(shí)多增加一個(gè)int類(lèi)型的參數(shù),但調(diào)用函數(shù)時(shí)該參數(shù)不用傳遞,編譯器
自動(dòng)傳遞
?注意:后置++是先使用后+1,因此需要返回+1之前的舊值,故需在實(shí)現(xiàn)時(shí)需要先將this保存
一份
,然后給this+1
?而temp是臨時(shí)對(duì)象,因此只能以值的方式返回,不能返回引用


 Date operator++(int)
 {
 Date temp(*this);
 _day += 1;
 return temp;
 }

1.5 const成員

將const修飾的“成員函數(shù)”稱(chēng)之為const成員函數(shù),const修飾類(lèi)成員函數(shù),實(shí)際修飾該成員函數(shù) 隱含的this指針,表明在該成員函數(shù)中不能對(duì)類(lèi)的任何成員進(jìn)行修改。

近萬(wàn)字的超詳細(xì)C++類(lèi)和對(duì)象,快進(jìn)來(lái)看看吧

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

這兩個(gè)默認(rèn)成員函數(shù)一般不用重新定義 ,編譯器默認(rèn)會(huì)生成。

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

 Date* operator&()
 {
 return this ;
 }
 const Date* operator&()const
 {
 return this ;
 }

2.初始化列表

初始化列表:以一個(gè)冒號(hào)開(kāi)始,接著是一個(gè)以逗號(hào)分隔的數(shù)據(jù)成員列表,每個(gè)"成員變量"后面跟 一個(gè)放在括號(hào)中的初始值或表達(dá)式。

Date(int year, int month, int day)

     : _year(2023)
     , _month(4)
     , _day(4)
 {}

注意:

1. 每個(gè)成員變量在初始化列表中只能出現(xiàn)一次(初始化只能初始化一次)

2. 類(lèi)中包含以下成員,必須放在初始化列表位置進(jìn)行初始化:

引用成員變量? ?const成員變量? ? 自定義類(lèi)型成員(且該類(lèi)沒(méi)有默認(rèn)構(gòu)造函數(shù)時(shí))

3.盡量使用初始化列表初始化,因?yàn)椴还苣闶欠袷褂贸跏蓟斜?,?duì)于自定義類(lèi)型成員變量, 一定會(huì)先使用初始化列表初始化。

4. 成員變量在類(lèi)中聲明次序就是其在初始化列表中的初始化順序,與其在初始化列表中的先后 次序無(wú)關(guān)

2.1 explicit關(guān)鍵字

構(gòu)造函數(shù)不僅可以構(gòu)造與初始化對(duì)象,對(duì)于單個(gè)參數(shù)或者除第一個(gè)參數(shù)無(wú)默認(rèn)值其余均有默認(rèn)值 的構(gòu)造函數(shù),還具有類(lèi)型轉(zhuǎn)換的作用。

以下是C++11規(guī)定的多參數(shù)構(gòu)造函數(shù)的隱式類(lèi)型轉(zhuǎn)換的舉例

單參構(gòu)造函數(shù)同理

using namespace std;

class A {
public:
	A(int a, int b,int c)
		: _year ( a),
	      _month (b),
	      _day (c)
	{

	}
	A(const A& a)
	{
		cout << "const A& " << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	A a = {1,2,3};
}

1. 單參/多參 構(gòu)造函數(shù),沒(méi)有使用explicit修飾,具有類(lèi)型轉(zhuǎn)換作用

?explicit修飾構(gòu)造函數(shù),禁止類(lèi)型轉(zhuǎn)換

3. static成員

3.1 概念:

聲明為static的類(lèi)成員稱(chēng)為類(lèi)的靜態(tài)成員,用static修飾的成員變量,稱(chēng)之為靜態(tài)成員變量;用 static修飾的成員函數(shù),稱(chēng)之為靜態(tài)成員函數(shù)。靜態(tài)成員變量一定要在類(lèi)外進(jìn)行初始化 面試題:實(shí)現(xiàn)一個(gè)類(lèi),計(jì)算程序中創(chuàng)建出了多少個(gè)類(lèi)對(duì)象。

3.2 特性

1. 靜態(tài)成員為所有類(lèi)對(duì)象所共享,不屬于某個(gè)具體的對(duì)象,存放在靜態(tài)區(qū)

2. 靜態(tài)成員變量必須在類(lèi)外定義,定義時(shí)不添加static關(guān)鍵字,類(lèi)中只是聲明

3. 類(lèi)靜態(tài)成員即可用 類(lèi)名::靜態(tài)成員 或者 對(duì)象.靜態(tài)成員 來(lái)訪問(wèn)

4. 靜態(tài)成員函數(shù)沒(méi)有隱藏的this指針,不能訪問(wèn)任何非靜態(tài)成員

5. 靜態(tài)成員也是類(lèi)的成員,受public、protected、private 訪問(wèn)限定符的限定

問(wèn)題:

1. 靜態(tài)成員函數(shù)可以調(diào)用非靜態(tài)成員函數(shù)嗎?不可以

2. 非靜態(tài)成員函數(shù)可以調(diào)用類(lèi)的靜態(tài)成員函數(shù)嗎?可以

例題:求1+2+3+...+n,要求不能使用乘除法、for、while、if、else、switch、case等關(guān)鍵字及條件判斷語(yǔ)句(A?B:C)。

使用靜態(tài)成員變量


using namespace std;


class Sum
	{
	public:
		Sum()
		{
			_sum += _n;
			++_n;
		}
	
		static int GetSum()
		{
			return _sum;
		}
	private:
		static int _n;
		static int _sum;
	};
	
	class Solution {
	public:
		int Sum_Solution(int n) {
			Sum* p = new Sum[n];
			return Sum::GetSum();
		}
		~Solution()
		{
			cout << "~Solution()" << endl;
		}
	};
	int Sum::_n = 1;
	int Sum::_sum = 0;
	int main()
	{
		cout << Solution().Sum_Solution(100) << endl;
	}

不使用靜態(tài)成員變量

class Solution {
public:
    int Sum_Solution(int n) {
        //通過(guò)與運(yùn)算判斷n是否為正數(shù),以結(jié)束遞歸
        n && (n += Sum_Solution(n - 1));
        return n;
    }
};

4. 友元

友元提供了一種突破封裝的方式,有時(shí)提供了便利。但是友元會(huì)增加耦合度,破壞了封裝,所以 友元不宜多用。 友元分為:友元函數(shù)和友元類(lèi)

4.1 友元函數(shù)?

近萬(wàn)字的超詳細(xì)C++類(lèi)和對(duì)象,快進(jìn)來(lái)看看吧

class Date
{
public:
Date(int year, int month, int day)
     : _year(year)
     , _month(month)
     , _day(day)
 {}
// d1 << cout; -> d1.operator<<(&d1, cout); 不符合常規(guī)調(diào)用
// 因?yàn)槌蓡T函數(shù)第一個(gè)參數(shù)一定是隱藏的this,所以d1必須放在<<的左側(cè)
ostream& operator<<(ostream& _cout)
 {
     _cout << _year << "-" << _month << "-" << _day << endl;
     return _cout;
 }
private:
int _year;
int _month;
int _day;
};

友元函數(shù)可以直接訪問(wèn)類(lèi)的私有成員,它是定義在類(lèi)外部的普通函數(shù),不屬于任何類(lèi),但需要在 類(lèi)的內(nèi)部聲明,聲明時(shí)需要加friend關(guān)鍵字。

class Date
{
	friend ostream& operator<<(ostream& _cout, const Date& d);
	friend istream& operator>>(istream& _cin, Date& d);
public:
	Date(int year = 1900, int month = 1, int day = 1)
		: _year(year)
		, _month(month)
		, _day(day)
	{}
private:
	int _year;
	int _month;
	int _day;
};
ostream& operator<<(ostream& _cout, const Date& d)
{
	_cout << d._year << "-" << d._month << "-" << d._day;
	return _cout;
}
istream& operator>>(istream& _cin, Date& d)
{
	_cin >> d._year;
	_cin >> d._month;
	_cin >> d._day;
	return _cin;
}
int main()
{
	Date d;
	cin >> d;
	cout << d << endl;
	return 0;
}

友元函數(shù)的說(shuō)明

友元函數(shù)可訪問(wèn)類(lèi)的私有和保護(hù)成員,但不是類(lèi)的成員函數(shù) 友元函數(shù)不能用const修飾

友元函數(shù)可以在類(lèi)定義的任何地方聲明,不受類(lèi)訪問(wèn)限定符限制

一個(gè)函數(shù)可以是多個(gè)類(lèi)的友元函數(shù)

友元函數(shù)的調(diào)用與普通函數(shù)的調(diào)用原理相同

4.2 友元類(lèi)

友元類(lèi)的所有成員函數(shù)都可以是另一個(gè)類(lèi)的友元函數(shù),都可以訪問(wèn)另一個(gè)類(lèi)中的非公有成員。

注意:

友元關(guān)系是單向的,不具有交換性。

比如下面代碼示例中的Time類(lèi)和Date類(lèi),在Time類(lèi)中聲明Date類(lèi)為其友元類(lèi),那么可以在Date類(lèi)中直接 訪問(wèn)Time類(lèi)的私有成員變量,但想在Time類(lèi)中訪問(wèn)Date類(lèi)中私有的成員變量則不行。

友元關(guān)系不能傳遞 如果C是B的友元, B是A的友元,則不能說(shuō)明C時(shí)A的友元。

友元關(guān)系不能繼承,在繼承位置再給大家詳細(xì)介紹。

代碼示例:

class Time
{
	friend class Date;   // 聲明日期類(lèi)為時(shí)間類(lèi)的友元類(lèi),則在日期類(lèi)中就直接訪問(wèn)Time類(lèi)中的私有成員變量
public:
	Time(int hour = 0, int minute = 0, int second = 0)
		: _hour(hour)
		, _minute(minute)
		, _second(second)
	{}

private:
	int _hour;
	int _minute;
	int _second;
};
class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1)
		: _year(year)
		, _month(month)
		, _day(day)
	{}

	void SetTimeOfDate(int hour, int minute, int second)
	{
		// 直接訪問(wèn)時(shí)間類(lèi)私有的成員變量
		_t._hour = hour;
		_t._minute = minute;
		_t._second = second;
	}

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

5. 內(nèi)部類(lèi)

概念:如果一個(gè)類(lèi)定義在另一個(gè)類(lèi)的內(nèi)部,這個(gè)內(nèi)部類(lèi)就叫做內(nèi)部類(lèi)。內(nèi)部類(lèi)是一個(gè)獨(dú)立的類(lèi), 它不屬于外部類(lèi),更不能通過(guò)外部類(lèi)的對(duì)象去訪問(wèn)內(nèi)部類(lèi)的成員。外部類(lèi)對(duì)內(nèi)部類(lèi)沒(méi)有任何優(yōu)越 的訪問(wèn)權(quán)限。

注意:內(nèi)部類(lèi)就是外部類(lèi)的友元類(lèi),參見(jiàn)友元類(lèi)的定義,內(nèi)部類(lèi)可以通過(guò)外部類(lèi)的對(duì)象參數(shù)來(lái)訪 問(wèn)外部類(lèi)中的所有成員。但是外部類(lèi)不是內(nèi)部類(lèi)的友元。

特性:

1. 內(nèi)部類(lèi)可以定義在外部類(lèi)的public、protected、private都是可以的。

2. 注意內(nèi)部類(lèi)可以直接訪問(wèn)外部類(lèi)中的static成員,不需要外部類(lèi)的對(duì)象/類(lèi)名。

3. sizeof(外部類(lèi))=外部類(lèi),和內(nèi)部類(lèi)沒(méi)有任何關(guān)系。

對(duì)上面例題進(jìn)行內(nèi)部類(lèi)封裝

class Solution {

  public:

    class Sum {
      public:
        Sum() {
            _sum += _n;
            ++_n;
        }

        static int GetSum() {
            return _sum;
        }

    };
    int Sum_Solution(int n) {
        Sum* p = new Sum[n];
        return Sum::GetSum();
    }
    ~Solution() {
        cout << "~Solution()" << endl;
    }
  private:
    static int _n;
    static int _sum;
};
int Solution::_n = 1;
int Solution::_sum = 0;

6.拷貝對(duì)象時(shí)的一些編譯器優(yōu)化

在傳參和傳返回值的過(guò)程中,一般編譯器會(huì)做一些優(yōu)化,減少對(duì)象的拷貝,這個(gè)在一些場(chǎng)景下還 是非常有用的。

6.1對(duì)象返回的總結(jié)

1.接受返回值的對(duì)象,盡量使用拷貝構(gòu)造方式接收,不要賦值接收。

2.函數(shù)中返回對(duì)象時(shí)盡量返回匿名對(duì)象。

6.2函數(shù)傳參的總結(jié)

盡量使用const &傳參。

7.匿名對(duì)象

但是我們可以這么定義匿名對(duì)象,匿名對(duì)象的特點(diǎn)不用取名字, 但是他的生命周期只有這一行文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-407903.html

		cout << Solution().Sum_Solution(100) << endl;

到了這里,關(guān)于近萬(wàn)字的超詳細(xì)C++類(lèi)和對(duì)象,快進(jìn)來(lái)看看吧的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶(hù)投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包