二十万字C/C++、嵌入式软开面试题全集宝典二
?
目錄
1、靜態(tài)綁定和動態(tài)綁定的介紹
2、C語言struct和C++struct區(qū)別
3、虛函數(shù)可以聲明為inline嗎?
4、介紹 C++ 所有的構(gòu)造函數(shù)
5、 什么情況下會調(diào)用拷貝構(gòu)造函數(shù)
6、 為什么拷貝構(gòu)造函數(shù)必須是引用傳遞,不能是值傳遞?
7、 何時需要合成構(gòu)造函數(shù)
8、 何時需要合成復制構(gòu)造函數(shù)
9、 C++類的虛函數(shù)表和虛函數(shù)在內(nèi)存中的位置
10、 同一個類,實例化多次,是否共享虛函數(shù)表?
11、 編譯器處理虛函數(shù)表應(yīng)該如何處理
?12、 類成員初始化方式?構(gòu)造函數(shù)的執(zhí)行順序?為什么用成員初始化列表會快一些?
一、初始化方式
13、 成員列表初始化?
14、 何時需要成員初始化列表?過程是什么?
15、 構(gòu)造函數(shù)為什么不能為虛函數(shù)?析構(gòu)函數(shù)為什么要虛函數(shù)?
16、 析構(gòu)函數(shù)的作用,如何起作用?
17、 構(gòu)造函數(shù)和析構(gòu)函數(shù)可以調(diào)用虛函數(shù)嗎,為什么
18、 構(gòu)造函數(shù)析構(gòu)函數(shù)可以調(diào)用虛函數(shù)嗎?
19、 構(gòu)造函數(shù)的執(zhí)行順序?析構(gòu)函數(shù)的執(zhí)行順序?構(gòu)造函數(shù)內(nèi)部干了啥?拷貝構(gòu)造干了啥?
20、 虛析構(gòu)函數(shù)的作用,父類的析構(gòu)函數(shù)是否要設(shè)置為虛函數(shù)?
?
1、靜態(tài)綁定和動態(tài)綁定的介紹
只有在存在虛函數(shù),并發(fā)生繼承時,基類指針或引用指向派生類對象時,才存在動態(tài)綁定。此時通過基類指針調(diào)用成員函數(shù)的話,如果調(diào)用的是虛函數(shù),則執(zhí)行派生類中的函數(shù),如果不是虛函數(shù),則調(diào)用基類的函數(shù)。
1.對象的靜態(tài)類型:對象在聲明時采用的類型。是在編譯期確定的。
2.對象的動態(tài)類型:目前所指對象的類型。是在運行期決定的。對象的動態(tài)類型可以更改,但是靜態(tài)類型無法更改。
3.靜態(tài)綁定:綁定的是對象的靜態(tài)類型,某特性(比如函數(shù))依賴于對象的靜態(tài)類型,發(fā)生在編譯期。
4.動態(tài)綁定:綁定的是對象的動態(tài)類型,某特性(比如函數(shù))依賴于對象的動態(tài)類型,發(fā)生在運行期。
2、C語言struct和C++struct區(qū)別
1、C語言中:struct是用戶自定義數(shù)據(jù)類型(UDT);C++中struct是抽象數(shù)據(jù)類型(ADT),支持成員函數(shù)的定義,(C++中的struct能繼承,能實現(xiàn)多態(tài))。
2、C中struct是沒有權(quán)限的設(shè)置的,且struct中只能是一些變量的集合體,可以封裝數(shù)據(jù)卻不可以隱藏數(shù)據(jù),而且成員不可以是函數(shù)。
3、C++中,struct的成員默認訪問說明符為public(為了與C兼容),class中的默認訪問限定符為private,struct增加了訪問權(quán)限,且可以和類一樣有成員函數(shù)。
4、struct作為類的一種特例是用來自定義數(shù)據(jù)結(jié)構(gòu)的。一個結(jié)構(gòu)標記聲明后,在C中必須在結(jié)構(gòu)標記前加上struct,才能做結(jié)構(gòu)類型名
3、虛函數(shù)可以聲明為inline嗎?
不能。
1、虛函數(shù)用于實現(xiàn)運行時的多態(tài),或者稱為靜態(tài)綁定或動態(tài)綁定。而內(nèi)聯(lián)函數(shù)用于提高效率。內(nèi)聯(lián)函數(shù)的原理是,在編譯期間,對調(diào)用內(nèi)聯(lián)函數(shù)的地方的代碼替換成函數(shù)代碼。內(nèi)聯(lián)函數(shù)對于程序中需要頻繁使用和調(diào)用的小函數(shù)非常有用。
2.虛函數(shù)要求在運行時進行類型確定,而內(nèi)聯(lián)函數(shù)要求在編譯期完成相關(guān)的函數(shù)替換;
4、介紹 C++ 所有的構(gòu)造函數(shù)
類的對象被創(chuàng)建時,編譯系統(tǒng)為對象分配內(nèi)存空間,并?動調(diào)?構(gòu)造函數(shù),由構(gòu)造函數(shù)完成成員的初始化?作。
即構(gòu)造函數(shù)的作?:初始化對象的數(shù)據(jù)成員。
1、?參數(shù)構(gòu)造函數(shù):即默認構(gòu)造函數(shù),如果沒有明確寫出?參數(shù)構(gòu)造函數(shù),編譯器會?動?成默認的?參數(shù)構(gòu)造函數(shù),函數(shù)為空,什么也不做,如果不想使??動?成的?參構(gòu)造函數(shù),必需要??顯示寫出?個?參構(gòu)造函數(shù)。
2、?般構(gòu)造函數(shù):也稱重載構(gòu)造函數(shù),?般構(gòu)造函數(shù)可以有各種參數(shù)形式,?個類可以有多個?般構(gòu)造函數(shù),前提是參數(shù)的個數(shù)或者類型不同,創(chuàng)建對象時根據(jù)傳?參數(shù)不同調(diào)?不同的構(gòu)造函數(shù)。
3、拷?構(gòu)造函數(shù):拷?構(gòu)造函數(shù)的函數(shù)參數(shù)為對象本身的引?,?于根據(jù)?個已存在的對象復制出?個新的該類的對象,?般在函數(shù)中會將已存在的對象的數(shù)據(jù)成員的值??復制到新創(chuàng)建的對象中。如果沒有顯示的寫拷?構(gòu)造函數(shù),則系統(tǒng)會默認創(chuàng)建?個拷?構(gòu)造函數(shù),但當類中有指針成員時,最好不要使?編譯器提供的默認的拷?構(gòu)造函數(shù),最好??定義并且在函數(shù)中執(zhí)?深拷?。
4、類型轉(zhuǎn)換構(gòu)造函數(shù):根據(jù)?個指定類型的對象創(chuàng)建?個本類的對象,也可以算是?般構(gòu)造函數(shù)的?種,這?提出來,是想說有的時候不允許默認轉(zhuǎn)換的話,要記得將其聲明為?explict?的,來阻??些隱式轉(zhuǎn)換的發(fā)?。
5、賦值運算符的重載:注意,這個類似拷?構(gòu)造函數(shù),將=右邊的本類對象的值復制給=左邊的對象,它不屬于構(gòu)造函數(shù),=左右兩邊的對象必需已經(jīng)被創(chuàng)建。如果沒有顯示的寫賦值運算符的重載,系統(tǒng)也會?成默認的賦值運算符,做?些基本的拷??作。
這?區(qū)分
A a1, A a2; a1 = a2;//調(diào)?賦值運算符
A a3 = a1;//調(diào)?拷?構(gòu)造函數(shù),因為進?的是初始化?作, a3 并未存在
5、 什么情況下會調(diào)用拷貝構(gòu)造函數(shù)
類的對象需要拷?時,拷?構(gòu)造函數(shù)將會被調(diào)?,以下的情況都會調(diào)?拷?構(gòu)造函數(shù):
1、?個對象以值傳遞的?式傳?函數(shù)體,需要拷?構(gòu)造函數(shù)創(chuàng)建?個臨時對象壓?到棧空間中。
2、?個對象以值傳遞的?式從函數(shù)返回,需要執(zhí)?拷?構(gòu)造函數(shù)創(chuàng)建?個臨時對象作為返回值。
3、?個對象需要通過另外?個對象進?初始化。
6、 為什么拷貝構(gòu)造函數(shù)必須是引用傳遞,不能是值傳遞?
為了防止遞歸調(diào)用。
當?個對象需要以值?式進?傳遞時,編譯器會?成代碼調(diào)?它的拷?構(gòu)造函數(shù)?成?個副本,如果類A的拷?構(gòu)造函數(shù)的參數(shù)不是引?傳遞,?是采?值傳遞,那么就?需要為了創(chuàng)建傳遞給拷?構(gòu)造函數(shù)的參數(shù)的臨時對象,???次調(diào)?類 A 的拷?構(gòu)造函數(shù),這就是?個?限遞歸。
1) 拷貝構(gòu)造函數(shù)的作用就是用來復制對象的,再使用這個對象的實例來初始化這個對象的一個新的實例。
2) 參數(shù)傳遞過程到底發(fā)生了什么?將地址傳遞和值傳遞統(tǒng)一起來,歸根結(jié)底還是傳遞的是"值"(地址也是值,只不過通過它可以找到另一個值)!
i)值傳遞:
對于內(nèi)置數(shù)據(jù)類型的傳遞時,直接賦值拷貝給形參(注意形參是函數(shù)內(nèi)局部變量);
對于類類型的傳遞時,需要首先調(diào)用該類的拷貝構(gòu)造函數(shù)來初始化形參(局部對象);如void foo(class_type obj_local){},?如果調(diào)用foo(obj); 首先class_type obj_local(obj)?,這樣就定義了局部變量obj_local供函數(shù)內(nèi)部使用
ii)引用傳遞:
無論對內(nèi)置類型還是類類型,傳遞引用或指針最終都是傳遞的地址值!而地址總是指針類型(屬于簡單類型), 顯然參數(shù)傳遞時,按簡單類型的賦值拷貝,而不會有拷貝構(gòu)造函數(shù)的調(diào)用(對于類類型)。
上述1) 2)回答了為什么拷貝構(gòu)造函數(shù)使用值傳遞會產(chǎn)生無限遞歸調(diào)用,內(nèi)存溢出。
拷貝構(gòu)造函數(shù)用來初始化一個非引用類類型對象,如果用傳值的方式進行傳參數(shù),那么構(gòu)造實參需要調(diào)用拷貝構(gòu)造函數(shù),而拷貝構(gòu)造函數(shù)需要傳遞實參,所以會一直遞歸。
7、 何時需要合成構(gòu)造函數(shù)
1.如果一個類沒有任何構(gòu)造函數(shù),但他含有一個成員對象,該成員對象含有默認構(gòu)造函數(shù),那么編譯器就為該類合成一個默認構(gòu)造函數(shù),因為不合成一個默認構(gòu)造函數(shù)那么該成員對象的構(gòu)造函數(shù)不能調(diào)用;
2.沒有任何構(gòu)造函數(shù)的類派生自一個帶有默認構(gòu)造函數(shù)的基類,那么需要為該派生類合成一個構(gòu)造函數(shù),只有這樣基類的構(gòu)造函數(shù)才能被調(diào)用;
3.帶有虛函數(shù)的類,虛函數(shù)的引入需要進入虛表,指向虛表的指針,該指針是在構(gòu)造函數(shù)中初始化的,所以沒有構(gòu)造函數(shù)的話該指針無法被初始化;
4.帶有一個虛基類的類
5.并不是任何沒有構(gòu)造函數(shù)的類都會合成一個構(gòu)造函數(shù)
6.編譯器合成出來的構(gòu)造函數(shù)并不會顯示設(shè)定類內(nèi)的每一個成員變量
8、 何時需要合成復制構(gòu)造函數(shù)
有三種情況會以一個對象的內(nèi)容作為另一個對象的初值:
1.對一個對象做顯示的初始化操作,X xx = x;
2.當對象被當做參數(shù)交給某個函數(shù)時;
3.當函數(shù)傳回一個類對象時;
9、 C++類的虛函數(shù)表和虛函數(shù)在內(nèi)存中的位置
C++類對象中虛函數(shù)表指針、虛函數(shù)表、虛函數(shù)之間的關(guān)系以及在內(nèi)存中的布局_子木呀的博客-CSDN博客
關(guān)系:虛函數(shù)表指針(保存在堆或棧)->虛函數(shù)表(常量區(qū)?.rodata)->虛函數(shù)(代碼段 .text)
虛函數(shù)表指針是虛函數(shù)表所在位置的地址。虛函數(shù)表指針屬于對象實例。因而通過new 出來的對象的虛函數(shù)表指針位于堆,聲名對象的虛函數(shù)表指針位于棧。
總結(jié):
1、虛函數(shù)表指針位置取決于對象在哪。如果是new的對象,則存在堆上,如果是直接聲明,則存在棧上。
2、虛函數(shù)表位于只讀數(shù)據(jù)段(.rodata),即:C++內(nèi)存模型中的常量區(qū);
3、虛函數(shù)代碼則位于代碼段(.text),也就是C++內(nèi)存模型中的代碼區(qū)。
10、 同一個類,實例化多次,是否共享虛函數(shù)表?
所有實例是共用一個虛函數(shù)表。
1.為什么要共用同一個虛函數(shù)表?可能是為了節(jié)省內(nèi)存吧,首先同一個類的對象虛函數(shù)都是一樣的,沒必要重新伴隨構(gòu)造生成一份一模一樣的表,所以拷貝虛函數(shù)表的表地址就行。
2.C++的編譯器應(yīng)該是保證虛函數(shù)表的指針存在于對象實例中最前面的位置(這是為了保證取到虛函數(shù)表的有最高的性能——假設(shè)有多層繼承或是多重繼承的情況下)。
3.這意味著我們通過對象實例的地址得到這張?zhí)摵瘮?shù)表。然后就能夠遍歷當中函數(shù)指針,并調(diào)用對應(yīng)的函數(shù)。
11、 編譯器處理虛函數(shù)表應(yīng)該如何處理
對于派?類來說,編譯器建?虛函數(shù)表的過程其實?共是三個步驟:
1、拷?基類的虛函數(shù)表,如果是多繼承,就拷?每個有虛函數(shù)基類的虛函數(shù)表
2、當?個基類的虛函數(shù)表和派?類?身的虛函數(shù)表是共用的?個虛函數(shù)表,也稱這個基類為派?類的主基類
3、查看派?類中是否有重寫基類中的虛函數(shù),如果有,就替換成已經(jīng)重寫的虛函數(shù)地址;
4、查看派?類是否有?身的虛函數(shù),如果有,就追加?身的虛函數(shù)到?身的虛函數(shù)表中。
Derived *pd = new D(); B *pb = pd; C *pc = pd;?其中 pb, pd, pc 的指針位置是不同的。
要注意的是派?類的?身的內(nèi)容要追加在主基類的內(nèi)存塊后,虛函數(shù)表指針始終在內(nèi)存最前面。
?12、 類成員初始化方式?構(gòu)造函數(shù)的執(zhí)行順序?為什么用成員初始化列表會快一些?
一、初始化方式
1.賦值初始化,通過在函數(shù)體內(nèi)進行賦值初始化;
2.列表初始化,在冒號后使用初始化列表進行初始化。
這兩種方式的主要區(qū)別在于:
1.對于賦值初始化,是在所有的數(shù)據(jù)成員被分配內(nèi)存空間后才進行的。
2.列表初始化是給數(shù)據(jù)成員分配內(nèi)存空間時就進行初始化,就是說分配一個數(shù)據(jù)成員只要冒號后有此數(shù)據(jù)成員的賦值表達式(此表達式必須是括號賦值表達式),那么分配了內(nèi)存空間后在進入函數(shù)體之前給數(shù)據(jù)成員賦值,就是說初始化這個數(shù)據(jù)成員此時函數(shù)體還未執(zhí)行。
二、列表初始化比賦值初始化更快的原因
賦值初始化是在構(gòu)造函數(shù)當中做賦值的操作,而列表初始化是做純粹的初始化操作。我們都知道,C++的賦值操作是會產(chǎn)生臨時對象的。臨時對象的出現(xiàn)會降低程序的效率。
三、一個派生類構(gòu)造函數(shù)的執(zhí)行順序如下:
1.虛擬基類的構(gòu)造函數(shù)(多個虛擬基類則按照繼承的順序執(zhí)行構(gòu)造函數(shù))。
2.基類的構(gòu)造函數(shù)(多個普通基類也按照繼承的順序執(zhí)行構(gòu)造函數(shù))。
3.類類型的成員對象的構(gòu)造函數(shù)(按照初始化順序)
4.派生類自己的構(gòu)造函數(shù)。
13、 成員列表初始化?
1.必須使用成員初始化的四種情況
①??當初始化一個引用成員時;
②??當初始化一個常量成員時;
③??當調(diào)用一個基類的構(gòu)造函數(shù),而它擁有一組參數(shù)時;
④??當調(diào)用一個成員類的構(gòu)造函數(shù),而它擁有一組參數(shù)時;
2.成員初始化列表做了什么
①??編譯器會一一操作初始化列表,以適當?shù)捻樞蛟跇?gòu)造函數(shù)之內(nèi)安插初始化操作,并且在任何顯示用戶代碼之前;
②??list中的項目順序是由類中的成員聲明順序決定的,不是由初始化列表的順序決定的;
14、 何時需要成員初始化列表?過程是什么?
1.當初始化一個引用成員變量時;
2.初始化一個const成員變量時;
3.當調(diào)用一個基類的構(gòu)造函數(shù),而構(gòu)造函數(shù)擁有一組參數(shù)時;
4.當調(diào)用一個成員類的構(gòu)造函數(shù),而他擁有一組參數(shù);
5.編譯器會一一操作初始化列表,以適當順序在構(gòu)造函數(shù)之內(nèi)安插初始化操作,并且在任何顯示用戶代碼前。list中的項目順序是由類中的成員聲明順序決定的,不是初始化列表中的排列順序決定的。
15、 構(gòu)造函數(shù)為什么不能為虛函數(shù)?析構(gòu)函數(shù)為什么要虛函數(shù)?
1.從存儲空間角度,虛函數(shù)相應(yīng)一個指向vtable虛函數(shù)表的指針,這大家都知道,但是這個指向vtable的指針事實上是存儲在對象的內(nèi)存空間的。問題出來了,假設(shè)構(gòu)造函數(shù)是虛的,就須要通過 vtable來調(diào)用,但是對象還沒有實例化,也就是內(nèi)存空間還沒有,怎么找vtable呢?所以構(gòu)造函數(shù)不能是虛函數(shù)。
2.從使用角度,虛函數(shù)主要用于在信息不全的情況下,能使重載的函數(shù)得到相應(yīng)的調(diào)用。構(gòu)造函數(shù)本身就是要初始化實例,那使用虛函數(shù)也沒有實際意義呀。所以構(gòu)造函數(shù)沒有必要是虛函數(shù)。虛函數(shù)的作用在于通過父類的指針或者引用來調(diào)用它的時候可以變成調(diào)用子類的那個成員函數(shù)。而構(gòu)造函數(shù)是在創(chuàng)建對象時自己主動調(diào)用的,不可能通過父類的指針或者引用去調(diào)用,因此也就規(guī)定構(gòu)造函數(shù)不能是虛函數(shù)。
3.構(gòu)造函數(shù)不須要是虛函數(shù),也不同意是虛函數(shù),由于創(chuàng)建一個對象時我們總是要明白指定對象的類型,雖然我們可能通過實驗室的基類的指針或引用去訪問它但析構(gòu)卻不一定,我們往往通過基類的指針來銷毀對象。這時候假設(shè)析構(gòu)函數(shù)不是虛函數(shù),就不能正確識別對象類型從而不能正確調(diào)用析構(gòu)函數(shù)。
4.從實現(xiàn)上看,vbtl在構(gòu)造函數(shù)調(diào)用后才建立,因而構(gòu)造函數(shù)不可能成為虛函數(shù)從實際含義上看,在調(diào)用構(gòu)造函數(shù)時還不能確定對象的真實類型(由于子類會調(diào)父類的構(gòu)造函數(shù));并且構(gòu)造函數(shù)的作用是提供初始化,在對象生命期僅僅運行一次,不是對象的動態(tài)行為,也沒有必要成為虛函數(shù)。
5.當一個構(gòu)造函數(shù)被調(diào)用時,它做的首要的事情之中的一個是初始化它的VPTR。因此,它僅僅能知道它是“當前”類的,而全然忽視這個對象后面是否還有繼承者。當編譯器為這個構(gòu)造函數(shù)產(chǎn)生代碼時,它是為這個類的構(gòu)造函數(shù)產(chǎn)生代碼——既不是為基類,也不是為它的派生類(由于類不知道誰繼承它)。所以它使用的VPTR必須是對于這個類的VTABLE。并且,僅僅要它是最后的構(gòu)造函數(shù)調(diào)用,那么在這個對象的生命期內(nèi),VPTR將保持被初始化為指向這個VTABLE, 但假設(shè)接著另一個更晚派生的構(gòu)造函數(shù)被調(diào)用,這個構(gòu)造函數(shù)又將設(shè)置VPTR指向它的 VTABLE,等.直到最后的構(gòu)造函數(shù)結(jié)束。VPTR的狀態(tài)是由被最后調(diào)用的構(gòu)造函數(shù)確定的。這就是為什么構(gòu)造函數(shù)調(diào)用是從基類到更加派生類順序的還有一個理由。可是,當這一系列構(gòu)造函數(shù)調(diào)用正發(fā)生時,每一個構(gòu)造函數(shù)都已經(jīng)設(shè)置VPTR指向它自己的VTABLE。假設(shè)函數(shù)調(diào)用使用虛機制,它將僅僅產(chǎn)生通過它自己的VTABLE的調(diào)用,而不是最后的VTABLE(全部構(gòu)造函數(shù)被調(diào)用后才會有最后的VTABLE)。
6.直接的講,C++中基類采用virtual虛析構(gòu)函數(shù)是為了防止內(nèi)存泄漏。具體地說,如果派生類中申請了內(nèi)存空間,并在其析構(gòu)函數(shù)中對這些內(nèi)存空間進行釋放。假設(shè)基類中采用的是非虛析構(gòu)函數(shù),當刪除基類指針指向的派生類對象時就不會觸發(fā)動態(tài)綁定,因而只會調(diào)用基類的析構(gòu)函數(shù),而不會調(diào)用派生類的析構(gòu)函數(shù)。那么在這種情況下,派生類中申請的空間就得不到釋放從而產(chǎn)生內(nèi)存泄漏。所以,為了防止這種情況的發(fā)生,C++中基類的析構(gòu)函數(shù)應(yīng)采用virtual虛析構(gòu)函數(shù)。
16、 析構(gòu)函數(shù)的作用,如何起作用?
1.構(gòu)造函數(shù)只是起初始化值的作用,但實例化一個對象的時候,可以通過實例去傳遞參數(shù),從主函數(shù)傳遞到其他的函數(shù)里面,這樣就使其他的函數(shù)里面有值了。規(guī)則,只要你實例化一個對象,系統(tǒng)自動會調(diào)用一個構(gòu)造函數(shù),就是你不寫,編譯器也自動調(diào)用一次。
2.析構(gòu)函數(shù)與構(gòu)造函數(shù)的作用相反,用于撤銷對象的一些特殊任務(wù)處理,可以是釋放對象分配的內(nèi)存空間;特點:析構(gòu)函數(shù)與構(gòu)造函數(shù)同名,但該函數(shù)前面加~。
3.析構(gòu)函數(shù)沒有參數(shù),也沒有返回值,而且不能重載,在一個類中只能有一個析構(gòu)函數(shù)。當撤銷對象時,編譯器也會自動調(diào)用析構(gòu)函數(shù)。每一個類必須有一個析構(gòu)函數(shù),用戶可以自定義析構(gòu)函數(shù),也可以是編譯器自動生成默認的析構(gòu)函數(shù)。一般析構(gòu)函數(shù)定義為類的公有成員。
17、 構(gòu)造函數(shù)和析構(gòu)函數(shù)可以調(diào)用虛函數(shù)嗎,為什么
1.在C++中,提倡不在構(gòu)造函數(shù)和析構(gòu)函數(shù)中調(diào)用虛函數(shù);
2.構(gòu)造函數(shù)和析構(gòu)函數(shù)調(diào)用虛函數(shù)時都不使用動態(tài)聯(lián)編,如果在構(gòu)造函數(shù)或析構(gòu)函數(shù)中調(diào)用虛函數(shù),則運行的是為構(gòu)造函數(shù)或析構(gòu)函數(shù)自身類型定義的版本;
3.因為父類對象會在子類之前進行構(gòu)造,此時子類部分的數(shù)據(jù)成員還未初始化,因此調(diào)用子類的虛函數(shù)時不安全的,故而C++不會進行動態(tài)聯(lián)編;
4.析構(gòu)函數(shù)是用來銷毀一個對象的,在銷毀一個對象時,先調(diào)用子類的析構(gòu)函數(shù),然后再調(diào)用基類的析構(gòu)函數(shù)。所以在調(diào)用基類的析構(gòu)函數(shù)時,派生類對象的數(shù)據(jù)成員已經(jīng)銷毀,這個時候再調(diào)用子類的虛函數(shù)沒有任何意義。
5.繼承類在構(gòu)造的時候總是首先調(diào)用其基類的構(gòu)造函數(shù)來對屬于其基類的部分進行構(gòu)造,在這個時候,整個類被當作基類來處理,繼承類的部分對整個類來說好像不存在一樣,直到基類的構(gòu)造函數(shù)退出并進入繼承類的構(gòu)造函數(shù),該類才被當作繼承類來出來處理。對析構(gòu)也一樣,只是析構(gòu)的順序正好相反。
18、 構(gòu)造函數(shù)析構(gòu)函數(shù)可以調(diào)用虛函數(shù)嗎?
1.在構(gòu)造函數(shù)最好不要調(diào)用虛函數(shù);
2.構(gòu)造函數(shù)或者析構(gòu)函數(shù)調(diào)用虛函數(shù)并不會發(fā)揮虛函數(shù)動態(tài)綁定的特性,跟普通函數(shù)沒區(qū)別;
3.即使構(gòu)造函數(shù)或者析構(gòu)函數(shù)如果能成功調(diào)用虛函數(shù),程序的運行結(jié)果也是不可控的。
lsy注:當有基類指針指向派生類時,需要將析構(gòu)函數(shù)定義為虛函數(shù)。
19、 構(gòu)造函數(shù)的執(zhí)行順序?析構(gòu)函數(shù)的執(zhí)行順序?構(gòu)造函數(shù)內(nèi)部干了啥?拷貝構(gòu)造干了啥?
1、構(gòu)造函數(shù)順序
1.基類構(gòu)造函數(shù)。如果有多個基類,則構(gòu)造函數(shù)的調(diào)用順序是某類在類派生表中出現(xiàn)的順序,而不是它們在成員初始化表中的順序。
2.成員類對象構(gòu)造函數(shù)。如果有多個成員類對象則構(gòu)造函數(shù)的調(diào)用順序是對象在類中被聲明的順序,而不是它們出現(xiàn)在成員初始化表中的順序。
3.派生類構(gòu)造函數(shù)。
2、析構(gòu)函數(shù)順序
1.調(diào)用派生類的析構(gòu)函數(shù);
2.調(diào)用成員類對象的析構(gòu)函數(shù);
3.調(diào)用基類的析構(gòu)函數(shù)。
20、 虛析構(gòu)函數(shù)的作用,父類的析構(gòu)函數(shù)是否要設(shè)置為虛函數(shù)?
1.C++中基類采用virtual虛析構(gòu)函數(shù)是為了防止內(nèi)存泄漏。具體地說,如果派生類中申請了內(nèi)存空間,并在其析構(gòu)函數(shù)中對這些內(nèi)存空間進行釋放。假設(shè)基類中采用的是非虛析構(gòu)函數(shù),當刪除基類指針指向的派生類對象時就不會觸發(fā)動態(tài)綁定,因而只會調(diào)用基類的析構(gòu)函數(shù),而不會調(diào)用派生類的析構(gòu)函數(shù)。那么在這種情況下,派生類中申請的空間就得不到釋放從而產(chǎn)生內(nèi)存泄漏。所以,為了防止這種情況的發(fā)生,C++中基類的析構(gòu)函數(shù)應(yīng)采用virtual虛析構(gòu)函數(shù)。
2.純虛析構(gòu)函數(shù)一定得定義,因為每一個派生類析構(gòu)函數(shù)會被編譯器加以擴張,以靜態(tài)調(diào)用的方式調(diào)用其每一個虛基類以及上一層基類的析構(gòu)函數(shù)。因此,缺乏任何一個基類析構(gòu)函數(shù)的定義,就會導致鏈接失敗。因此,最好不要把虛析構(gòu)函數(shù)定義為純虛析構(gòu)函數(shù)。
總結(jié)
以上是生活随笔為你收集整理的二十万字C/C++、嵌入式软开面试题全集宝典二的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 二十万字C/C++、嵌入式软开面试题全集
- 下一篇: 关于mysql的项目_项目中常用的MyS