最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

C++自制心得——類與對象上

2023-08-29 16:46 作者:這年頭起名可真不容易  | 我要投稿

前言:?

從這里開始,我們將面對C++的第一個攔路虎,類與對象。這里的內(nèi)容大概要寫四個專欄,開篇一章,六大成員函數(shù)兩章,收尾一章,每一章都是超級大長篇,請做好心里準備。而且,至少在類與對象這一節(jié),沒有幾個語言比C++更麻煩,一是C++需要向下兼容C語言,二是C++出的早,坑會多。廢話不多講,我們開始吧。

1.類與結(jié)構(gòu)體

我們這里不講面向?qū)ο蟮木唧w定義,別人都講爛了,自己找一個看就是。我們從結(jié)構(gòu)體開始講,在C++里,結(jié)構(gòu)體直接被升級成了類,同時也保有了C語言原本的用法。

s1是C語言用法,s2是C++的用法。升級后的結(jié)構(gòu)體支持成員函數(shù),并且定義對象時也不用加struct關(guān)鍵字了。

不過在實際應(yīng)用中我們更喜歡用類來代替結(jié)構(gòu)體,如圖

但是換成類以后程序就跑不了了,如圖

這是什么錯誤,你不是說結(jié)構(gòu)體被升級成了類嗎?怎么換了類就報錯了。其實類與結(jié)構(gòu)體還是有一點區(qū)別的,那就是默認訪問限定符的不同。

訪問限定符有三種類型,public(公有),private(私有),protected(保護),目前,我們可以認為私有和保護是一樣的(它們的區(qū)別在繼承和多態(tài)才有體現(xiàn),現(xiàn)在只講封裝)

被public修飾的成員可以在類外通過正常方式訪問,而被private修飾的成員不能在類外通過正常方式訪問。而結(jié)構(gòu)體的默認訪問限定符為公有,類的默認訪問限定符為私有,這就是報錯原因。

那么,類將private作為默認修飾符有什么好處嗎?上代碼

這里有一個棧,現(xiàn)在我們想訪問其棧頂元素,那就寫一個top函數(shù)訪問,一句話的事。不過,某些人喜歡用另一種方案,他們覺得訪問棧頂元素可以直接用top變量訪問,沒必要寫一個函數(shù),想法還不錯,但是......

為什么結(jié)果是隨機值,我相信觀眾們都清楚,不過這種編程思路就反映出C語言的一大痛點,過于自由。作為代碼的設(shè)計者,我們自然希望用戶只通過我們提供的接口使用代碼,而不希望用戶自由訪問。顯然用private修飾我們不想讓用戶訪問的成員是很科學的,這就是封裝的好處。

2.類的聲明與定義

這個問題很簡單,我就直接貼代碼了

stack.h

stack.cpp

前四個成員函數(shù)不用管,后面會講,我們看后面的。類的聲明定義規(guī)則實際上是函數(shù)聲明定義與結(jié)構(gòu)體聲明定義的集成,成員變量的聲明定義按照結(jié)構(gòu)體的來,成員函數(shù)的聲明定義按照函數(shù)的來,唯一需要注意的是成員函數(shù)的定義處在全局而非類域里,所以定義處需要添加::

3.成員變量風格

你應(yīng)該已經(jīng)發(fā)現(xiàn)了,我給出的示例代碼里成員變量在前面都有“_”符號,你可能在學習C語言的時候也被告知要給成員變量加修飾。這當然是有理由的,我以日期類的init來舉例子。

如果你不給成員變量加修飾,那這個init就起不到它應(yīng)有的功能,編譯器會將它認定為自己給自己賦值(你要愿意用this當我沒說)?

這就行了。

4.實例化

可以這么寫代碼嗎?

不行,因為這個類沒有實例化,我們訪問的只是一個類型

將類比作房子圖紙,實例化的對象比作房子,邏輯會很清晰,房子的圖紙不能住人,但房子可以。把圖紙變成房子的過程就是實例化,這個過程就會給對象開空間,你就能訪問了。

再看一個問題,對象d1占用多少空間?根據(jù)內(nèi)存對齊可以得出d1的成員變量所占空間為12字節(jié),但是成員函數(shù)占不占空間?不知道,那就試試。

哦,結(jié)果是12,看上去成員函數(shù)不占對象空間,事實也的確如此。實例化對象只會給成員變量開空間,而成員函數(shù)不會進入具體對象本身,而是會進入公共代碼區(qū)。這是符合邏輯的,成員變量需要有很多份,而函數(shù)只需要一份,顯然,把成員函數(shù)放入對象就是一件特別浪費的事情。

上點難度,這三個對象的空間是多少?

揭曉答案

第一二個很好理解,默認對齊數(shù)為8,所以第一個對齊數(shù)為4,第二個對齊數(shù)為8,所以占用空間為8和24,但是第三個為什么是1,不是0。是這樣的,如果第三個是0,我們就無法區(qū)分多個A3類的對象,因此我們象征性的給了一個字節(jié)以示區(qū)分。

5.this指針

你覺得init函數(shù)里的成員變量是誰的成員變量?

哪個對象調(diào)用了這個函數(shù),函數(shù)里的成員變量就是那個對象的。但是從表面上看init函數(shù)的形參只有年月日要被賦的值,沒有調(diào)用對象的年月日,那么編譯器是怎么做到這一點的?答案就是this指針。C++給每一個成員函數(shù)都添加了一個隱含參數(shù)this指針,固定為函數(shù)的第一形參,指向調(diào)用對象,不可更改指向(類型 + * const this),并且其調(diào)用和傳參均由編譯器自動進行,不可顯式寫出,但在函數(shù)里可顯式寫出。如果我們把this指針顯式寫出,那應(yīng)該是這樣的

( ̄▽ ̄)現(xiàn)在我要出三道題,看看各位對this指針的理解是否到位。

第一個代碼的運行結(jié)果是:A. 編譯錯誤? B. 運行錯誤 C. 正常運行

第二個代碼的運行結(jié)果是:A. 編譯錯誤? B. 運行錯誤 C. 正常運行

第三個代碼的運行結(jié)果是:A. 編譯錯誤? B. 運行錯誤 C. 正常運行

揭曉答案,CCB

以我在這一塊學習的經(jīng)驗來說一定有很多人選BBB。那么各位要想清楚一個問題,在a->print()這句代碼里,print()是不是a直接指向的?No,前面我們說了,成員函數(shù)不在對象里,在公共代碼區(qū),那實際上a直接指向的只有int x,顯然,在第一二種情況里,a壓根沒有解引用,代碼實際上只完成了nullptr的拷貝,而沒有解引用,所以代碼可以正常運行。只有第三種情況我們解引用了nullptr。為了驗證我的結(jié)論,以第一種情況為例,我們?nèi)シ磪R編。

看見了嗎,a->print()只干了兩件事,將nullptr賦給ecx寄存器(C++覺得this指針會被經(jīng)常調(diào)用,所以會把this指針存在寄存器里,而非進行壓棧操作),調(diào)用print函數(shù),沒有解引用操作。

下面再出兩道面試題:

1. this指針可以為空嗎?

2. this指針存在哪里?

第一題我們演示過了,可以為空。第二題的答案是棧區(qū),為什么,因為this是函數(shù)形參,函數(shù)形參存在棧區(qū)(有沒有人寫this指針存在對象里?有沒有?有沒有?)

可喜可賀,類與對象上終于講完了,下一個就是六大成員函數(shù),到時候,等著被虐吧。

C++自制心得——類與對象上的評論 (共 條)

使用qq登录你需要登录后才可以评论。
临猗县| 迁安市| 竹溪县| 平罗县| 微山县| 宝鸡市| 北票市| 南川市| 沾化县| 中宁县| 通道| 东至县| 周至县| 宜黄县| 任丘市| 南宁市| 永和县| 西平县| 新巴尔虎右旗| 那坡县| 三河市| 岑巩县| 乐清市| 石首市| 山西省| 延吉市| 渭南市| 喀什市| 城固县| 镇雄县| 巴里| 金沙县| 和政县| 武定县| 定结县| 玉树县| 无锡市| 河北区| 平利县| 镇江市| 新平|