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

C嘎嘎~~[構造函數(shù)提升篇]

這篇具有很好參考價值的文章主要介紹了C嘎嘎~~[構造函數(shù)提升篇]。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

1. 再談構造函數(shù)

1.1. 引入

1.1.1問題引入

class Date
{
public:
private:
	int _year;
	int _month;
	int _day;
};

通過前面所學的知識, 我們知道了_year, _month, _day這三個變量都是一些聲明, 并沒有開辟空間, 不是定義.

Date d1;

這一個操作就是給 d1這個對象整體定義, 但是對象整體定義,并不代表著里面的三個成員變量定義了.

???那么問題來了: 成員變量是在什么時候定義的??

1.1.2 const引入

class Date
{
public:

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

int main()
{
	Date d1;
	
	return 0;
}

當我們用const 來修飾一下其中的一個成員變量, 那么會怎么樣了?
C嘎嘎~~[構造函數(shù)提升篇]
???這樣的報錯是什么意思? — 具有未初始化的常量限定數(shù)據(jù)成員

  • 其實我們可以發(fā)現(xiàn)一些端倪: 就是const 修飾的變量有一個特點就是 定義的時候一定要初始化, 那么有些老鐵就會說 在里面給 const修飾的變量一個缺省值試一試
    C嘎嘎~~[構造函數(shù)提升篇]
    ???這些不是聲明嘛, 給一個缺省值為什么就可以了? 原理是什么啊? 還有就是傳一個缺省值是傳給誰啊?
  • 其實, 初始化列表可以看成成員變量定義的地方. 而我們給的缺省值也是給初始化列表用的. 缺省, 缺省, 說實話就是一個備胎, 如果我們在初始化列表中給了這個變量的值? 那么就不會用這個缺省值了, 而去用我們在初始化列表中的值.

1.2 正篇

在構造函數(shù)中,初始化成員變量有兩種方式: 構造函數(shù)體賦值初始化列表
其實, 這兩種方式是有所不同的, 通過下面的一些比較就能看出他們的不同

1.2.1 構造函數(shù)體賦值

class Date
{
public:
	Date(int year, int month, int day)
	{
		_year = year;
		_year = 2022;

		_month = month;
		_month = 5;

		_day = day;
		_day = 20;
	}

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

int main()
{
	Date d1(2023, 5, 16);

	return 0;
}

???延續(xù)上面的問題, 這個是不是初始化?

  • 其實答案很明顯, 這個是并不是初始化. 因為每一個變量只有一次初始化, 但是可以有多次賦值. 通過上面的代碼, 我們可以發(fā)現(xiàn): 在構造函數(shù)內(nèi)部可以進行多次的賦值, 而初始化只有一次, => 構造函數(shù)不是成員變量初始化的地方

1.2.2 初始化列表

1.2.3.1 淺淺認識

初始化列表: 以一個冒號開始, 接著用一個逗號分隔數(shù)據(jù)成員列表, 每一個 成員變量后面跟一個放在括號中的初始值或者表達式

class Date
{
public:
    // 構造函數(shù)
	Date()
	     // 此部分是 初始化列表
		:_year(2023)
		// 此部分是 構造函數(shù)體賦值
	{
		_month = 5;
		_day = 16;
	}

private:
	const int _year; // const 修飾的成員變量
	int _month;
	int _day;
};

int main()
{
	Date d1;

	return 0;
}
  • 注意:
    1. 每個成員變量在初始化列表中 最多出現(xiàn)一次(因為只能初始化一次)
    2. 類中包含以下的成員時, 必須放在初始化列表中進行初始化:
    • const 修飾的成員變量
    • 引用修飾的成員變量
    • 沒有默認構造函數(shù)的自定義類型
1.2.3.2 構造函數(shù)的 行走順序

構造函數(shù)初始化成員變量有兩種形式: 構造函數(shù)體賦值初始化列表
一個是 賦值, 一個是 初始化 ? 由此不難看出, 編譯器先走的是 初始化列表然后才是構造函數(shù)體賦值

???如果沒有初始化列表, 編譯器會走初始化列表這一步嗎?

  • 猛一看, 感覺這個問題是不是有問題; 仔細一想, 其實這個問題問的很有深度~~. 換一句話說, 其實這個問題是想問 ? 初始化列表是構造函數(shù)必走的一步嗎?
    通過下面的代碼, 驗證一番:
class Date
{
public:
	Date()
	{
		_month = 5;
		_day = 16;
	}

	void Print()
	{
		cout << _year << " " << _month << " " << _day << endl;
	}

private:
	const int _year = 5;
	int _month;
	int _day;
};

int main()
{
	Date d1;
	d1.Print(); // 5 5 16

	return 0;
}
class Date
{
public:
	Date()
		:_year(2023)
	{
		_month = 5;
		_day = 16;
	}

	void Print()
	{
		cout << _year << " " << _month << " " << _day << endl;
	}

private:
	const int _year = 5;
	int _month;
	int _day;
};

int main()
{
	Date d1;
	d1.Print(); //2023 5 16

	return 0;
}

通過上面的兩個例子:

  1. 補丁 — — 成員變量給個缺省值, 這個缺省值其實傳給初始化列表的. 如果初始化列表沒有對此變量進行操作, 那么就會使用那個缺省值
  2. 初始化列表是構造函數(shù)必走的一步 — — 因為初始化列表是成員變量定義的地方C嘎嘎~~[構造函數(shù)提升篇]
1.2.3.3 引用修飾成員變量
class A
{
public:
	A(int a, int& b)
	{
		_a1 = a;
		_a2 = b;
	}
private:
	int _a1;
	int& _a2;
};

int main()
{
	int n = 10;
	A a(10, n);

	return 0;
}

*****
error C2530: “A::_a2”: 必須初始化引用
*****

???有一些老鐵, 就會有一些疑問: 為什么這里的傳引用不能傳遞一個常量? 就比如 A a(10, 10);

  • 首先這樣寫會有報錯的:
    C嘎嘎~~[構造函數(shù)提升篇]
    在這里, 我們只需要看一下紅色的報錯(藍色的報錯是這一類 的錯誤 — — 不能用構造函數(shù)體賦值來初始化 用引用修飾的成員變量):
    因為 _a2 是 b的引用, b 是 10的引用 ? _a2 是 10的引用, 由于 10是一個常量, 所以引用都要用常量引用來接收, 否則就是引用的權限放大造成錯誤!!!
    如果我們這樣修改的話, 就必須把成員變量里面也用 const來修飾此變量才可以. 不過這樣多不方便? 傳一個常量, 一直用, 還不能改變? 這不符合我們的需求啊~
    C嘎嘎~~[構造函數(shù)提升篇]

通過上面的例子, 我們發(fā)現(xiàn): 使用構造函數(shù)體賦值這種方式是不行的!!

那么, 我們就采用初始化列表:
C嘎嘎~~[構造函數(shù)提升篇]

  • _a2 = 10 — — _a2 是 b的引用, b 是 n的引用 ? _a2 是 n的引用. 因為初始化列表是成員變量定義的地方, 所以可以在此處進行對 引用修飾的_a2 進行初始化
  • _a1 是一個隨機值 — — 發(fā)現(xiàn)傳參的 10沒用? 想告訴各位讀者的是, 我們傳參是有自己的目的性 和 選擇性; 如果我們不用, 對于內(nèi)置類型成員變量(當然也沒有缺省值)就會被初始化為隨機值.
1.2.3.4 沒有默認構造的自定義類型
class B
{
public:
	// 無參調(diào)用 ==> 默認構造
	B()
	{

	}
private:
	int _b;
	int _tem;
};

class A
{
public:

private:
	int _a;
	B bb;
};

int main()
{
	A a1;

	return 0;
}

上面的代碼是正確的, 因為A 類中有一個自定義類型的成語變量 bb. 構造函數(shù)是完成成員變量的初始化的, 對于 A類來說, 要完成 對 _a 和 bb( _b _tem) 的初始化. 而要完成對 bb的初始化, 就需要 B類的默認構造. 如果 B類存在默認構造, 那么就會對 bb 進行初始化, 如果 B類不存在默認構造, 那么就不會對 bb進行初始化.??????

class B
{
public:
	// 有參 ==> 就不存在默認構造
	B(int x, int y)
	{
		_b = x;
		_tem = y;
	}
private:
	int _b;
	int _tem;
};

class A
{
public:

private:
	int _a;
	B bb;
};

int main()
{
	A a1;

	return 0;
}

C嘎嘎~~[構造函數(shù)提升篇]

上面, 我們故意對 B類的構造函數(shù)寫成了有參調(diào)用? 那么 B類就會失去默認構造=> B(_b _ tem) 就會是隨機值, 就不能完成對 B(_b _ tem) 的初始化了=> A類中就不能完成初始化

  • 那我們試一試初始化列表??????

C嘎嘎~~[構造函數(shù)提升篇]


  • 自定義類型成員變量的初始化總結:
    C嘎嘎~~[構造函數(shù)提升篇]

1.2.3初始化列表的 '坑'

成員變量在類中聲明次序就是在初始化列表中的初始化順序, 與其在初始化列表中的先后次序無關

class A
{
public:
	A(int a)
		:_a1(a)
		,_a2(_a1)
	{}

private:
	int _a2;
	int _a1;
};

int main()
{
	A a(1);

}

???上面代碼的運行結果是什么?

  • _a2 是隨機值, _a1 = 1
    因為聲明中的順序是 _a2 _a1, 那么編譯器在初始化列表初始化的時候就會 先初始化 _a2, 再初始化_a1 ?
    初始化 _a2 的時候: _a2( _a1), 這時候_a1還沒有被初始化, 所以是一個隨機值; 初始化 _a1的時候: _a1(1), 那么 _a1就是 1嘍

建議— — 盡量按照聲明的順序來安排初始化列表中變量的初始化順序

初始化列表中, 每一個成員變量最多只能出現(xiàn)一次

class A
{
public:
	A()
		:_a1(5)
		,_a2(10)
		,_a1(8)
	{}

private:
	int _a2;
	int _a1;
};

int main()
{
	A a;

	return 0;
}

C嘎嘎~~[構造函數(shù)提升篇]

  • 初始化列表是每個成員變量定義的地方, 也是初始化的地方

1.2.4 談談初始化列表 和 構造函數(shù)

其實, 每一個初學者在這個地方都會停留一段時間.
初始化列表 和 構造函數(shù), 一不留神就會混淆了概念和作用

總的來說, 初始化列表是構造函數(shù)的一部分.構造函數(shù)的功能就是完成對成員變量的初始化工作, 對自定義類型會調(diào)用它的默認構造, 而對于內(nèi)置類型, 就不會進行處理.
完成這一個初始化工作, 有兩個方式: 初始化列表構造函數(shù)體賦值. 見名知義: 一個是初始化, 一個是賦值.
如果成員變量中 沒有 const修飾, 引用修飾 或者 沒有默認構造的自定義類型, 寫不寫初始化列表都是ok的, 只要有其中的一個存在, 就要寫一下初始化列表. 其實const修飾的成員變量也可以不用寫初始化列表(上面有例子, 不清楚的上去看看)
比較來說, 初始化列表可以完成的工作 > 構造函數(shù)體賦值 ? 我們一般建議使用初始化列表. 當然有些工作時需要構造函數(shù)體賦值, 也是要寫構造函數(shù)體賦值的.


1.3 explicit關鍵字

1.3.1 引入

前面C語言的學習, 我們知道存在一種 類型轉換. 由于C++能夠兼容C語言, 我們就大膽實驗??????

class A
{
public:
	A(int a)
		:_a(a)
	{}

private:
	int _a;

};

int main()
{
	A a = 23;

	return 0;
}

上面的代碼是可行的.
???為什么可以直接從一個 int類型直接轉換成 A類的對象a呢?? 中間出現(xiàn)了什么過程呢??

  • 構造函數(shù)不僅可以構造與初始化對象, 對于單個參數(shù)或者第一個參數(shù)無默認值其余有默認值的構造函數(shù), 還具有類型轉換的作用
1.3.2 正篇
1.3.2.1 賦值的含義

???先有一個問題: 在C語言的學習中, 以int a = 10; double b = a; 為例子, 講述一下 類型轉換的過程

  • 類型轉換不是直接就 把 a 的值 賦值給 b. 會生成一個 類型為 double的臨時變量, 記作 tem , 然后把tem 賦值給 b . 這里多說一句, 后面就出現(xiàn)了引用 &, 就不會有臨時對象的生成.

那么延續(xù)上面的思路, 我們就會知道上面代碼的一個原理:
用 23去構造了一個 類型為A的臨時對象, 記作tem, 然后把 tem 拷貝構造給 a
???為啥換到這里就是 構造 和 拷貝構造了??

  • 生成一個類型是 A的臨時對象 tem, 用 23去初始化tem — — 構造
    用一個已知的對象tem 去初始化另一個對象 a — — 拷貝構造
1.3.2.2 探尋 '隱式類型轉換' 的真相

我們已經(jīng)知道隱式類型轉換的一個原理, 那么用代碼來驗證一番:

class A
{
public:
	A(int a)
		:_a(a)
	{
		cout << "調(diào)用了構造函數(shù)" << endl;
	}

	A(const A& x)
	{
		cout << "調(diào)用了拷貝構造函數(shù)" << endl;
	}

private:
	int _a;
};

int main()
{
	A a = 23;

	return 0;
}

*****
調(diào)用了構造函數(shù)
*****

???嗯??, 跟我們想的不一樣, 難道我們想錯了??

  • 其實不然, 這里編譯器把它給優(yōu)化了.
    我們知道: 構造 和 拷貝構造 的功能都是 初始化, 如果在同一行, 我們同時調(diào)用 構造 + 拷貝構造 ? 編譯器就只會調(diào)用一個構造函數(shù), 直接完成賦值~~

???老陳, 你空口無憑, 給我們看一下證據(jù)??

  • ok, 這就安排
    由于,臨時對象具有常性, 所以我們想到了用 引用 &來進行驗證 <== 因為權限可以縮小 或 平移, 但是不能放大
    先看下面的代碼??????
class A
{
public:
	A(int a)
		:_a(a)
	{
		cout << "調(diào)用了構造函數(shù)" << endl;
	}

	A(const A& x)
	{
		cout << "調(diào)用了拷貝構造函數(shù)" << endl;
	}

private:
	int _a;
};

int main()
{
	A& a = 23;

	return 0;
}

*****
error C2440: “初始化”: 無法從“int”轉換為“A &*****
class A
{
public:
	A(int a)
		:_a(a)
	{
		cout << "調(diào)用了構造函數(shù)" << endl;
	}

	A(const A& x)
	{
		cout << "調(diào)用了拷貝構造函數(shù)" << endl;
	}

private:
	int _a;
};

int main()
{
	const A& a = 23;

	return 0;
}

*****
調(diào)用了構造函數(shù)
*****

這里就變相地證明了: 上面的隱式類型轉換 是經(jīng)歷過了構造 + 拷貝構造, 不過是編譯器有優(yōu)化而已
注意: 不同的編譯器有不同的優(yōu)化, 所以看到不同的結果不必大驚小怪的~~

1.3.2.3 explicit關鍵字

在一些場景下, 隱式類型轉換會很方便(后面會學到的 string, STL… …),
但在另一些場景下, 我們又不希望隱式類型轉換的出現(xiàn)(后面會學到的 智能指針… …)
那我們?nèi)绾?code>不讓 隱式類型轉換 發(fā)生呢?? — — 答案就是explicit關鍵字
把explicit 放在 構造函數(shù)的前面就會不讓 隱式類型轉換發(fā)生

class A
{
public:
	explicit A(int a)
		:_a(a)
	{
		cout << "調(diào)用了構造函數(shù)" << endl;
	}

	A(const A& x)
	{
		cout << "調(diào)用了拷貝構造函數(shù)" << endl;
	}

private:
	int _a;
};

int main()
{
	A a = 23;

	return 0;
}

*****
error C2440: “初始化”: 無法從“int”轉換為“A”
message : class“A”的構造函數(shù)聲明為“explicit*****

大鵬一日同風起,扶搖直上九萬里文章來源地址http://www.zghlxwxcb.cn/news/detail-470098.html

到了這里,關于C嘎嘎~~[構造函數(shù)提升篇]的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

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

領支付寶紅包贊助服務器費用

相關文章

  • 【Flutter】dart構造函數(shù)、工廠構造函數(shù)

    在OOP中,我們會使用類來定義一類對象的屬性,和行為。通過調(diào)用該類的構造函數(shù)來創(chuàng)建類的實例對象。在通過調(diào)用方法來實現(xiàn)操作行為。 和大多數(shù) OOP 語言一樣, dart 的構造函數(shù),采用和類同名的函數(shù)名作為構造函數(shù), 不顯示聲明構造函數(shù)會自動創(chuàng)建無參構造,構造函數(shù)不

    2024年01月21日
    瀏覽(20)
  • 【C++初階】類和對象——構造函數(shù)&&析構函數(shù)&&拷貝構造函數(shù)

    【C++初階】類和對象——構造函數(shù)&&析構函數(shù)&&拷貝構造函數(shù)

    ========================================================================= 個人主頁點擊直達: 小白不是程序媛 C++系列專欄: C++頭疼記 ========================================================================= 目錄 前言 類的6個默認成員函數(shù) 構造函數(shù) 概念 構造函數(shù)的特性 析構函數(shù) 概念 析構函數(shù)特性 拷貝構

    2024年02月06日
    瀏覽(57)
  • C++ 類和對象(二)構造函數(shù)、析構函數(shù)、拷貝構造函數(shù)

    C++ 類和對象(二)構造函數(shù)、析構函數(shù)、拷貝構造函數(shù)

    ????????本文將介紹類的6個默認成員函數(shù)中的構造函數(shù)、析構函數(shù)和拷貝構造函數(shù),賦值重載和取地址重載涉及運算符重載的知識,將在下篇講解。所謂默認成員函數(shù),也就是每個類都有的成員函數(shù),我們可以顯式定義這些函數(shù),否則,編譯器會自動生成它們。 目錄 前言

    2024年02月09日
    瀏覽(41)
  • ?【C++要笑著學】(7) 默認成員函數(shù):構造函數(shù) | 析構函數(shù) | 拷貝構造函數(shù)

    ?【C++要笑著學】(7) 默認成員函數(shù):構造函數(shù) | 析構函數(shù) | 拷貝構造函數(shù)

    ?? 訂閱量破千的火熱 C++ 教程 ?? 火速訂閱 《C++要笑著學》? ??? CSDN 累計訂閱量破千的火爆 C/C++ 教程的 2023 重制版,C 語言入門到實踐的精品級趣味教程。 了解更多: ?? ?\\\"不太正經(jīng)\\\" 的專欄介紹? ← 試讀第一章 訂閱鏈接: ?? 《C語言趣味教程》?← 猛戳訂閱! ? 本篇

    2024年02月07日
    瀏覽(39)
  • 【C++】類與對象(構造函數(shù)、析構函數(shù)、拷貝構造函數(shù)、常引用)

    【C++】類與對象(構造函數(shù)、析構函數(shù)、拷貝構造函數(shù)、常引用)

    ?????個人主頁: 秦jh__https://blog.csdn.net/qinjh_?spm=1010.2135.3001.5343 ???系列專欄: ? 目錄 類的6個默認成員函數(shù) 構造函數(shù) 特性 ?析構函數(shù) 特性 ?析構的順序 拷貝構造函數(shù) 特性 常引用 ???? ?? hello! 各位鐵子們大家好哇。 ? ? ? ? ? ? ?今日更新了類與對象的構造函數(shù)、

    2024年02月21日
    瀏覽(20)
  • C++:構造方法(函數(shù));拷貝(復制)構造函數(shù):淺拷貝、深拷貝;析構函數(shù)。

    C++:構造方法(函數(shù));拷貝(復制)構造函數(shù):淺拷貝、深拷貝;析構函數(shù)。

    1.構造方法(函數(shù)) 構造方法是一種特殊的成員方法,與其他成員方法不同: 構造方法的名字必須與類名相同; 無類型、可有參數(shù)、可重載 會自動生成,可自定義 一般形式:類名(形參); 例: Stu(int age); 當用戶沒自定義構造方法時,系統(tǒng)將會執(zhí)行默認構造方法,當用戶自定義一個

    2024年02月11日
    瀏覽(20)
  • 【C++】初始化列表構造函數(shù)VS普通構造函數(shù)

    初始化列表構造函數(shù)最優(yōu)先匹配問題 對于一個類而言,只要其中包含有初始化列表的構造函數(shù),編譯器在編譯使用{}語法的構造時會最傾向于調(diào)用初始化列表構造函數(shù),哪怕做類型轉換也在所不惜,哪怕有類型最佳匹配的普通構造函數(shù)或移動構造函數(shù)也會被劫持 編譯器這種熱

    2024年02月05日
    瀏覽(41)
  • c++(8.23)類,this指針,構造函數(shù),析構函數(shù),拷貝構造函數(shù)

    c++(8.23)類,this指針,構造函數(shù),析構函數(shù),拷貝構造函數(shù)

    設計一個Per類,類中包含私有成員:姓名、年齡、指針成員身高、體重,再設計一個Stu類,類中包含私有成員:成績、Per類對象 p1,設計這兩個類的構造函數(shù)、析構函數(shù)和拷貝構造函數(shù)。

    2024年02月11日
    瀏覽(22)
  • 如何在 Java 中從另一個構造函數(shù)調(diào)用一個構造函數(shù)?

    是否可以從另一個(在同一個類中,而不是從子類中)調(diào)用構造函數(shù)?如果是怎么辦?調(diào)用另一個構造函數(shù)的最佳方法是什么(如果有幾種方法可以做到)? huntsbot.com高效搞錢,一站式跟進超10+任務平臺外包需求 對的,這是可能的: 要鏈接到特定的超類構造函數(shù)而不是同一

    2024年02月03日
    瀏覽(19)
  • 【C++初階】四、類和對象(構造函數(shù)、析構函數(shù)、拷貝構造函數(shù)、賦值運算符重載函數(shù))

    【C++初階】四、類和對象(構造函數(shù)、析構函數(shù)、拷貝構造函數(shù)、賦值運算符重載函數(shù))

    ========================================================================= 相關代碼gitee自取 : C語言學習日記: 加油努力 (gitee.com) ?========================================================================= 接上期 : 【C++初階】三、類和對象 (面向過程、class類、類的訪問限定符和封裝、類的實例化、類對象模

    2024年02月05日
    瀏覽(32)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

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

二維碼1

領取紅包

二維碼2

領紅包