最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++深入刨析類與對(duì)象的使用

 更新時(shí)間:2022年05月26日 08:53:48   作者:?jiǎn)虇碳业凝堼? 
類和對(duì)象是兩種以計(jì)算機(jī)為載體的計(jì)算機(jī)語(yǔ)言的合稱。對(duì)象是對(duì)客觀事物的抽象,類是對(duì)對(duì)象的抽象。類是一種抽象的數(shù)據(jù)類型;變量就是可以變化的量,存儲(chǔ)在內(nèi)存中—個(gè)可以擁有在某個(gè)范圍內(nèi)的可變存儲(chǔ)區(qū)域

this指針

現(xiàn)在給出一段代碼,實(shí)現(xiàn)一個(gè)普通的日期 date 的打印:

class date
{
public:
	void print()
	{
		cout << year<<' ' << month <<' '<< day << endl;
	}
	void init(int y, int m, int d)
	{
		year = y;
		month = m;
		day = d;
	}
private:
	int year;
	int month;
	int day;
};
int main()
{
	date d1;
	date d2;
	date d3;
	d1.init(2022, 5, 15);
	d2.init(2022, 5, 14);
	d3.init(2022, 5, 13);
	d1.print();
	d2.print();
	d3.print();
	return 0;
}

結(jié)果如你所想:

那么問題來了,d1,d2,d3在調(diào)用類里面的 print 函數(shù)時(shí),并沒有指明對(duì)象或者給出形參,最后結(jié)果卻能打印出不同的三個(gè)結(jié)果,這是為什么呢?、

這就是C++語(yǔ)法中的隱藏的 this 指針這里的 this 指針其實(shí)就是隱含的形參,這個(gè)形參會(huì)對(duì)函數(shù)進(jìn)行處理,比如剛剛的 print 函數(shù)以及他的調(diào)用,他們的真面目其實(shí)是這樣:

void print(date* this)

{ cout<< this->year << ’ ’ << this->month << ’ ’ << this->day << endl; }

d1->init(&d1,2022,5,15);

也就是說所有成員變量前面都會(huì)有一個(gè) this 指針修飾(實(shí)際上 this 指針是個(gè) const 類型,指針不能修改但指向內(nèi)容可以修改),使得形參和實(shí)參之間架起一座無(wú)形的橋梁,進(jìn)行連結(jié)。值得注意的是,這個(gè)過程是編譯器在搗鼓實(shí)現(xiàn)的,不需要我們自己去搞,要是寫的時(shí)候強(qiáng)行帶上 this 指針反而還會(huì)報(bào)錯(cuò)。

那數(shù)據(jù)是如何對(duì)應(yīng)上的呢?換個(gè)問題就是 print 每次是怎么樣對(duì)應(yīng)上 d1,d2,d3的,其實(shí)訪問成員變量年月日,并不是在訪問 private 里的年月日,private 里只是聲明并不存在空間的開辟,訪問但是同一個(gè)類里面的 init 函數(shù)從而訪問到成員變量。

this指針存放在哪

this 指針存在寄存器里面!

其實(shí)編譯器在生成程序時(shí)加入了獲取對(duì)象首地址的相關(guān)代碼。并把獲取的首地址存放在了寄存器ECX中(VC++編譯器是放在ECX中,其它編譯器有可能不同)。也就是成員函數(shù)的其它參數(shù)正常都是存放在棧中,而this指針參數(shù)則是存放在寄存器中。

類的靜態(tài)成員函數(shù)因?yàn)闆]有this指針這個(gè)參數(shù),所以類的靜態(tài)成員函數(shù)也就無(wú)法調(diào)用類的非靜態(tài)成員變量。

nullptr與類

如果我定義了一個(gè)空值指針,讓空值指針分別去訪問我類里面的函數(shù)與成員變量會(huì)怎么樣:

class Data
{
public:
	void print()
	{
		cout << "hello" << endl;
	}
	void printa()
	{
		cout << a << endl;
	}
private:
	int a;
};
int main()
{
	Data* n = nullptr;
	n->print();//訪問函數(shù)
	n->printa();//訪問成員變量
	return 0;
}

結(jié)果如圖:

沒錯(cuò),程序崩潰辣!但是很明顯,hello 打印出來了就說明函數(shù)的訪問是沒有問題的,但是是沒有辦法訪問成員變量的。

我們說類里面用空指針訪問函數(shù),成員變量結(jié)果會(huì)不同,原因就是函數(shù)在公共代碼區(qū),不需要解引用,直接找到函數(shù)地址變成 call 地址即可,而成員變量的訪問需要解引用自然空指針就會(huì)寄。

空指針 nullptr 其實(shí)并不是真的“空”,實(shí)際上是真實(shí)存在的,他指向虛擬進(jìn)程空間里面地址為 0 的地方,這個(gè) 0 地址處是用來程序初始化的,是預(yù)留出來的,并不是用來存儲(chǔ)數(shù)據(jù)的。因此空指針一旦指向數(shù)據(jù),這個(gè)數(shù)據(jù)就是不被認(rèn)可的,沒有意義的。

類的默認(rèn)成員函數(shù)

類里面什么都沒有,就稱它為空類,實(shí)際上空類中真的什么都沒有嗎?答案是 NO!任何一個(gè)類在默認(rèn)情況下都會(huì)生成 6 個(gè)成員函數(shù)。

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

構(gòu)造函數(shù)是特殊的成員函數(shù),需要注意的是,構(gòu)造函數(shù)雖然名叫構(gòu)造,但他的主要任務(wù)并不是開辟空間或者創(chuàng)建對(duì)象,而是將對(duì)象初始化。我們不寫,編譯器也會(huì)生成一個(gè)默認(rèn)無(wú)參數(shù)的構(gòu)造函數(shù),但這個(gè)默認(rèn)的構(gòu)造函數(shù)不一定有用,而 C++11打的補(bǔ)丁,針對(duì)編輯器自己生成的默認(rèn)成員函數(shù)不初始化的問題,給了缺省值來供默認(rèn)構(gòu)造函數(shù)使用。

需要注意的是:

  1. 類名與函數(shù)名保持一致
  2. 可以不用傳參,沒有返回值
  3. 對(duì)象實(shí)例化時(shí)編輯器自動(dòng)調(diào)用對(duì)應(yīng)的構(gòu)造函數(shù)
  4. 構(gòu)造函數(shù)支持函數(shù)重載
  5. 如果類中沒有顯式定義構(gòu)造函數(shù),C++編譯器會(huì)自動(dòng)生成一個(gè)無(wú)參的默認(rèn)構(gòu)造函數(shù),如果我們自己顯式定義了就不會(huì)給出了
  6. 無(wú)參的構(gòu)造函數(shù)和全缺省的構(gòu)造函數(shù)都被稱為默認(rèn)構(gòu)造函數(shù),并且默認(rèn)構(gòu)造函數(shù)只能有一個(gè)

意義

C++將變量分為兩種:內(nèi)置類型(int,char,指針類型等等)和自定義類型(struct/class 去定義的類型對(duì)象)

而這正好就是 C++ 語(yǔ)法設(shè)計(jì)的一個(gè)敗筆,他會(huì)導(dǎo)致

如果有內(nèi)置類型的成員就得自己寫構(gòu)造函數(shù),比如:

class Stack
{
public:
     void push(int x){
     }
     void pop(){
     }
private:
     Stack stackpush;
     Stack stackpop;
}

該類里面只有自定義類型成員變量,就不需要去寫構(gòu)造函數(shù),默認(rèn)的構(gòu)造函數(shù)就可以完成了??偨Y(jié)一下就是如果類里面只有自義定類型,就可以用默認(rèn)構(gòu)造函數(shù),如果存在內(nèi)置類型或者需要顯示傳參初始化就需要自己寫構(gòu)造函數(shù)。

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

如果構(gòu)造函數(shù)高速了我們對(duì)象是怎么來的,那么析構(gòu)函數(shù)就是在告訴我們對(duì)象是怎么走的。析構(gòu)函數(shù)與構(gòu)造函數(shù)功能相反,他并不是完成了對(duì)象的銷毀,因?yàn)榫植繉?duì)象銷毀是由編譯器來完成,而析構(gòu)函數(shù)是完成對(duì)象的一些資源清理工作,他是在對(duì)象銷毀時(shí)自動(dòng)調(diào)用。

再三強(qiáng)調(diào)不是銷毀對(duì)象本身!不是銷毀對(duì)象本身!所謂的資源清理針對(duì)的對(duì)象是 malloc,new 或者 fopen 這類的操作進(jìn)行清理收尾,其實(shí)本質(zhì)上就相當(dāng)于我們之前的 destroy 函數(shù)。

其特征如下:

  1. 析構(gòu)函數(shù)名是在類名前面加上字符 -
  2. 無(wú)參數(shù)也無(wú)返回值
  3. 一個(gè)類有且僅有一個(gè)析構(gòu)函數(shù),如果沒有顯式定義,系統(tǒng)會(huì)自動(dòng)生成析構(gòu)函數(shù)
  4. 對(duì)象聲明周期結(jié)束時(shí),C++編譯系統(tǒng)自動(dòng)調(diào)用析構(gòu)函數(shù)

但是注意一個(gè)順序問題:

int main()
{
Stack st1;
Stack st2;
return 0;
}

st1 相比 st2 先構(gòu)造這沒什么問題,但 st2 卻比 st1 先析構(gòu),析構(gòu)和構(gòu)造的順序是相反的。但他和構(gòu)造函數(shù)一樣,對(duì)內(nèi)置類型不處理但是對(duì)于自定義類型會(huì)去調(diào)用。

拷貝構(gòu)造

有沒有可能你會(huì)想搞一個(gè)和自己一樣的對(duì)象出來呢?如果想那就該我拷貝構(gòu)造登場(chǎng)辣!

int main()
{
     Date d1(2022,5,16);
     Date d2(d1);
     return 0;
}

這里的 d2 就是拿 d1 來初始化,所以拷貝構(gòu)造只有單個(gè)形參,該形參是對(duì)類類型對(duì)象的引用,一般由 const 修飾,再用已存在的類類型對(duì)象創(chuàng)建新對(duì)象時(shí)由編譯器自動(dòng)調(diào)用。他實(shí)際上是構(gòu)造函數(shù)的一種函數(shù)重載,他的參數(shù)只要一個(gè),而且必須使用引用傳參,因?yàn)槭褂脗髦禃?huì)引發(fā)無(wú)窮遞歸調(diào)用。

在什么情況下系統(tǒng)會(huì)調(diào)用拷貝構(gòu)造函數(shù):

(1)用類的一個(gè)對(duì)象去初始化另一個(gè)對(duì)象時(shí)

(2)當(dāng)函數(shù)的形參是類的對(duì)象時(shí)(也就是值傳遞時(shí)),如果是引用傳遞則不會(huì)調(diào)用

(3)當(dāng)函數(shù)的返回值是類的對(duì)象或引用時(shí)

C++規(guī)定了自義定類型對(duì)象,拷貝初始化要調(diào)用拷貝構(gòu)造完成。這就引出來一個(gè)問題,比如我們拷貝棧,定義了兩個(gè)對(duì)象 st1 和 st2,假如我寫成下面的樣子就會(huì)出亂子:

Stack st1(1);
Stack st2(st1);

因?yàn)槭强截悩?gòu)造, st2 指向地址和 st1 是一樣的,這并不是我們想要的結(jié)果,我們傳統(tǒng)拷貝是指向同一塊空間,而且這里拷貝構(gòu)造會(huì)崩,原因很簡(jiǎn)單,這里原理上進(jìn)行的是淺拷貝,默認(rèn)構(gòu)造函數(shù)會(huì)對(duì)類里面內(nèi)置類型進(jìn)行淺拷貝,值拷貝,對(duì)于自義定類型,編譯器不知道自義定類型的行為,如何拷貝,什么規(guī)則,像 stack 這種類型就需要深拷貝實(shí)現(xiàn),我們后面再去學(xué)習(xí)。

淺拷貝是按位拷貝對(duì)象,它會(huì)創(chuàng)建一個(gè)新對(duì)象,這個(gè)對(duì)象有著原始對(duì)象屬性值的一份精確拷貝。如果屬性是基本類型,拷貝的就是基本類型的值;如果屬性是內(nèi)存地址(引用類型),拷貝的就是內(nèi)存地址 ,因此如果其中一個(gè)對(duì)象改變了這個(gè)地址,就會(huì)影響到另一個(gè)對(duì)象。

st1 構(gòu)建完成變成 st2 參數(shù)去初始化 st2,st2 一旦拷貝完成就要進(jìn)行析構(gòu),而析構(gòu)會(huì)先執(zhí)行 st2 ,st2 一旦被清理這塊空間就會(huì)被銷毀,而此時(shí) st1 還在使用這塊空間,就會(huì)導(dǎo)致內(nèi)存錯(cuò)誤。

運(yùn)算符重載

說到運(yùn)算符重載,這里面有幾分門道嗷。他是個(gè)啥呢?

您可以重定義或重載大部分 C++ 內(nèi)置的運(yùn)算符,這樣就能使用自定義類型的運(yùn)算符。重載的運(yùn)算符是帶有特殊名稱的函數(shù),函數(shù)名是由關(guān)鍵字 operator 和其后要重載的運(yùn)算符符號(hào)構(gòu)成的。與其他函數(shù)一樣,重載運(yùn)算符有一個(gè)返回類型和一個(gè)參數(shù)列表。

說的比較玄學(xué),其實(shí)你設(shè)想一下這個(gè)場(chǎng)景,假如我們給出的日期類有兩個(gè)成員 d1,d2,我們?nèi)绻ケ容^他們能用運(yùn)算符 ==,<,> 來比較嗎,或者我給日期 +、- 一個(gè)數(shù)可以嗎,很明顯不行,因?yàn)閮?nèi)置類型可以直接使用運(yùn)算符,但是自義定類型不可以,因此就引入了我們的運(yùn)算符重載。

運(yùn)算符重載——函數(shù),函數(shù)名:operator +運(yùn)算符,參數(shù)是運(yùn)算符的操作數(shù),如下:

operator==(Date d1,Date d2)
{
      return d1.year == d2.year
      && d1.month == d2.month
      && d1.day == d2.day
}

細(xì)心的你可能會(huì)問,內(nèi)置類型我定義在私有域里面該怎么訪問呢?這就有三種方法:

  1. 從根源解決,改成公有類型public(尬活了屬于是)
  2. 再寫一個(gè)公有域的函數(shù)來調(diào)用私有域的內(nèi)置類型成員;
  3. C++ 友元(后續(xù)會(huì)學(xué)習(xí)到)

先別覺得ez,因?yàn)檫@里他會(huì)報(bào)錯(cuò)

==是要求的兩個(gè)參數(shù),我這里也是兩個(gè)參數(shù)沒錯(cuò)啊,為什么會(huì)參數(shù)太多???別忘了,操作符還有 默認(rèn)的形參 this,他被限定為第一個(gè)形參,因此我們只需要寫一個(gè)參數(shù)即可:

operator==(Date d)
{
      return year == d.year
      && month == d.month
      && day == d.day
}

編譯器遇到 if(d1 == d2) 這樣的語(yǔ)句,就會(huì)去處理成對(duì)應(yīng)的重載運(yùn)算符調(diào)用 if(d1.operator(d2)),這里編譯器時(shí)很聰明的,你寫的全局他會(huì)去調(diào)用全局,你寫的成員他會(huì)去調(diào)用成員。而且遇到運(yùn)算符重載他會(huì)在優(yōu)先去類里面找,沒有才回去類外面找,也就是說類的里外同時(shí)存在運(yùn)算符重載函數(shù)是可以編譯過去的。

注意一下

::

sizeof

?:

.

.*

這五個(gè)操作符是不能進(jìn)行重載的,在選擇題中會(huì)經(jīng)常出現(xiàn)。

到此這篇關(guān)于C++深入刨析類與對(duì)象的使用的文章就介紹到這了,更多相關(guān)C++類與對(duì)象內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++中const的用法詳細(xì)總結(jié)

    C++中const的用法詳細(xì)總結(jié)

    以下是對(duì)C++中const的用法進(jìn)行了詳細(xì)的總結(jié)分析,需要的朋友可以過來參考下,希望對(duì)大家有所幫助
    2013-09-09
  • C/C++連接MySQL數(shù)據(jù)庫(kù)詳細(xì)圖文教程

    C/C++連接MySQL數(shù)據(jù)庫(kù)詳細(xì)圖文教程

    在實(shí)際開發(fā)中我們經(jīng)常需要對(duì)數(shù)據(jù)庫(kù)進(jìn)行訪問,下面這篇文章主要介紹了C/C++連接MySQL數(shù)據(jù)庫(kù)的詳細(xì)圖文教程,文中通過代碼以及圖文介紹是非常詳細(xì),需要的朋友可以參考下
    2024-01-01
  • C++異常使用詳解(看這一篇就夠了)

    C++異常使用詳解(看這一篇就夠了)

    C++中的異常是指在程序執(zhí)行過程中發(fā)生錯(cuò)誤,導(dǎo)致程序無(wú)法正常運(yùn)行的情況,下面這篇文章主要給大家介紹了關(guān)于C++異常使用的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-10-10
  • C語(yǔ)言數(shù)組長(zhǎng)度的計(jì)算方法實(shí)例總結(jié)(sizeof與strlen)

    C語(yǔ)言數(shù)組長(zhǎng)度的計(jì)算方法實(shí)例總結(jié)(sizeof與strlen)

    數(shù)組一旦創(chuàng)建,程序運(yùn)行期間,長(zhǎng)度不可改變,下面這篇文章主要給大家介紹了關(guān)于C語(yǔ)言數(shù)組長(zhǎng)度的計(jì)算方法,主要利用的是sizeof與strlen,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-06-06
  • 詳解C語(yǔ)言編程中預(yù)處理器的用法

    詳解C語(yǔ)言編程中預(yù)處理器的用法

    這篇文章主要介紹了C語(yǔ)言編程中預(yù)處理器的用法,包括介紹了C和C++混合編程的情況,需要的朋友可以參考下
    2016-02-02
  • C語(yǔ)言簡(jiǎn)明介紹常見關(guān)鍵字的用法

    C語(yǔ)言簡(jiǎn)明介紹常見關(guān)鍵字的用法

    關(guān)鍵字是C語(yǔ)言非常重要的一部分,熟練的掌握和使用關(guān)鍵字有助于我們更加熟悉了解C語(yǔ)言,同時(shí)C語(yǔ)言的關(guān)鍵字也是面試筆試中??嫉膬?nèi)容。C語(yǔ)言的關(guān)鍵字共有32個(gè),但并不是每個(gè)關(guān)鍵字都有坑,本篇文章將通過理論聯(lián)系實(shí)際的方式為大家講解C語(yǔ)言中易混易錯(cuò)以及??嫉囊恍╆P(guān)鍵字
    2022-06-06
  • 簡(jiǎn)要解讀C++的動(dòng)態(tài)和靜態(tài)關(guān)聯(lián)以及虛析構(gòu)函數(shù)

    簡(jiǎn)要解讀C++的動(dòng)態(tài)和靜態(tài)關(guān)聯(lián)以及虛析構(gòu)函數(shù)

    這篇文章主要介紹了簡(jiǎn)要解讀C++的動(dòng)態(tài)和靜態(tài)關(guān)聯(lián)以及虛析構(gòu)函數(shù),析構(gòu)函數(shù)在C++編程中平時(shí)并不是太常用,需要的朋友可以參考下
    2015-09-09
  • C語(yǔ)言中g(shù)etchar()的原理以及易錯(cuò)點(diǎn)解析

    C語(yǔ)言中g(shù)etchar()的原理以及易錯(cuò)點(diǎn)解析

    用getchar()函數(shù)讀取字符串時(shí),字符串會(huì)存儲(chǔ)在輸入緩沖區(qū)中,包括輸入的回車字符,下面這篇文章主要給大家介紹了關(guān)于C語(yǔ)言中g(shù)etchar()的原理以及易錯(cuò)點(diǎn)解析的相關(guān)資料,需要的朋友可以參考下
    2022-03-03
  • C++基于socket多線程實(shí)現(xiàn)網(wǎng)絡(luò)聊天室

    C++基于socket多線程實(shí)現(xiàn)網(wǎng)絡(luò)聊天室

    這篇文章主要為大家詳細(xì)介紹了C++基于socket多線程實(shí)現(xiàn)網(wǎng)絡(luò)聊天室,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-07-07
  • C++ 約瑟夫環(huán)問題案例詳解

    C++ 約瑟夫環(huán)問題案例詳解

    這篇文章主要介紹了C++ 約瑟夫環(huán)問題案例詳解,本篇文章通過簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08

最新評(píng)論

宁明县| 鄂尔多斯市| 静安区| 定日县| 宣化县| 河南省| 蒲江县| 永平县| 庆城县| 元阳县| 米脂县| 灌阳县| 三台县| 白银市| 应用必备| 蒙阴县| 东乡县| 通河县| 深泽县| 红原县| 集贤县| 汉阴县| 齐齐哈尔市| 菏泽市| 西畴县| 瑞昌市| 浦东新区| 新竹市| 霸州市| 巴南区| 禄劝| 许昌市| 新余市| 伊宁市| 洛川县| 阿克苏市| 潍坊市| 泰顺县| 房山区| 乾安县| 遂溪县|