<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          打工人的面試題集錦

          共 18392字,需瀏覽 37分鐘

           ·

          2021-08-21 01:42


          前言: 經(jīng)常回顧C(jī)/C++面試題和筆試題,有助于我們對(duì)C/C++基礎(chǔ)有一個(gè)新的認(rèn)識(shí)和記憶。在實(shí)際工作中,大部分人會(huì)被業(yè)務(wù)纏身,基礎(chǔ)慢慢的遺忘了,對(duì)很多基礎(chǔ)知識(shí)欲言又止!回顧筆試面試題目,會(huì)讓我們對(duì)基礎(chǔ)知識(shí)掌握更加牢固,同時(shí)筆試題也有助于我們開闊思路,提高編程能力,還有就是開源代碼閱讀,只有不斷的回顧和學(xué)習(xí),才能不斷的進(jìn)步。

          加油吧!打工人!~


          面試題 1:內(nèi)存對(duì)齊的原則以及作用?
          (1)結(jié)構(gòu)體內(nèi)的成員按自身長度自對(duì)齊(32位機(jī)器上,如char=1,short=2,int=4,double=8),所謂自對(duì)齊是指該成員的起始地址必須是它自身長度的整數(shù)倍。如int只能以0,4,8這類地址開始。
          (2)結(jié)構(gòu)體的總大小為結(jié)構(gòu)體的有效對(duì)齊值的整數(shù)倍(默認(rèn)以結(jié)構(gòu)體中最長的成員長度為有效值的整數(shù)倍,當(dāng)用#pragrma pack(n)指定時(shí),以n和結(jié)構(gòu)體中最長的成員的長度中較小者為其值)。即sizeof的值,必須是其內(nèi)部最大成員的整數(shù)倍,不足的要補(bǔ)齊。
          例如:
          class A
          {
              char c;
              int a;
              char d;
          };
           
          cout << sizeof(A) << endl;
           
          class B
          {
              char c;
              char d;
              int a;
          };
           
          cout << sizeof(B) << endl;
          sizeof(A)=12,sizeof(B)=8;
          因?yàn)樽筮吺?+(3)+4+1+(3)=12,而右邊是1+1+(2)+4=8。括號(hào)中為補(bǔ)齊的字節(jié)。
          內(nèi)存對(duì)齊的作用:
          1、平臺(tái)原因(移植原因):不是所有的硬件平臺(tái)都能訪問任意地址上的任意數(shù)據(jù)的;某些硬件平臺(tái)只能在某些地址處取某些特定類型的數(shù)據(jù),否則拋出硬件異常。
          2、性能原因:經(jīng)過內(nèi)存對(duì)齊后,CPU的內(nèi)存訪問速度大大提升。

          面試題 2:變量的聲明和定義有什么區(qū)別
          為變量分配地址和存儲(chǔ)空間的稱為定義,不分配地址的稱為聲明。一個(gè)變量可以在多個(gè)地方聲明,但是只在一個(gè)地方定義。加入 extern 修飾的是變量的聲明,說明此變量將在文件以外或在文件后面部分定義。說明:很多時(shí)候一個(gè)變量,只是聲明不分配內(nèi)存空間,直到具體使用時(shí)才初始化,分配內(nèi)存空間, 如外部變量。

          面試題 3:explicit關(guān)鍵字的作用
          C++中, 一個(gè)參數(shù)的 構(gòu)造函數(shù)(或者除了第一個(gè)參數(shù)外其余參數(shù)都有默認(rèn)值的多參構(gòu)造函數(shù)), 承擔(dān)了兩個(gè)角色。1 是個(gè) 構(gòu)造器 ,2 是個(gè)默認(rèn)且隱含的類型轉(zhuǎn)換操作符。
          所以, 有時(shí)候在我們寫下如 AAA = XXX, 這樣的代碼, 且恰好XXX的類型正好是AAA單參數(shù)構(gòu)造器的參數(shù)類型, 這時(shí)候 編譯器就自動(dòng)調(diào)用這個(gè)構(gòu)造器, 創(chuàng)建一個(gè)AAA的對(duì)象。
          這樣看起來好象很酷, 很方便。但在某些情況下(見下面權(quán)威的例子), 卻違背了我們(程序員)的本意。這時(shí)候就要在這個(gè)構(gòu)造器前面加上explicit修飾, 指定這個(gè)構(gòu)造器只能被明確的調(diào)用/使用, 不能作為類型轉(zhuǎn)換操作符被隱含的使用。
          class Test1
          {
          public:
              Test1(int n)
              {
                  num=n;
              }//普通構(gòu)造函數(shù)
          private:
              int num;
          };
          class Test2
          {
          public:
              explicit Test2(int n)
              {
                  num=n;
              }//explicit(顯式)構(gòu)造函數(shù)
          private:
              int num;
          };
          int main()
          {
              Test1 t1=12;//隱式調(diào)用其構(gòu)造函數(shù),成功
              Test2 t2=12;//編譯錯(cuò)誤,不能隱式調(diào)用其構(gòu)造函數(shù)
              Test2 t2(12);//顯式調(diào)用成功
              return 0;
          }
          Test1的 構(gòu)造函數(shù)帶一個(gè)int型的參數(shù),代碼23行會(huì)隱式轉(zhuǎn)換成調(diào)用Test1的這個(gè)構(gòu)造函數(shù)。而Test2的構(gòu)造函數(shù)被聲明為explicit(顯式),這表示不能通過隱式轉(zhuǎn)換來調(diào)用這個(gè)構(gòu)造函數(shù),因此代碼24行會(huì)出現(xiàn)編譯錯(cuò)誤。
          普通構(gòu)造函數(shù)能夠被 隱式調(diào)用。而explicit構(gòu)造函數(shù)只能被顯式調(diào)用。

          面試題 4:寫出 bool 、int、 float、指針變量與“零值”比較的 if 語句
          bool 型數(shù)據(jù): 
          if( flag ) 

            A; 

          else 

            B; 

          int 型數(shù)據(jù): 
          if0 != flag ) 

            A; 

          else { 
            B; 

          指針型數(shù): 
          if( NULL == flag ) 

            A; 

          else { 
            B; 

          float 型數(shù)據(jù): 
          if ( ( flag >= NORM ) && ( flag <= NORM ) ) 

            A; 

          注意:應(yīng)特別注意在 int、指針型變量和“零值”比較的時(shí)候,把“零值”放在左邊,這樣當(dāng)把“==” 誤寫成“=”時(shí),編譯器可以報(bào)錯(cuò),否則這種邏輯錯(cuò)誤不容易發(fā)現(xiàn),并且可能導(dǎo)致很嚴(yán)重的后果。

          面試題 5:內(nèi)存溢出,內(nèi)存泄漏的原因?
          內(nèi)存溢出是指程序在申請(qǐng)內(nèi)存時(shí),沒有足夠的內(nèi)存空間供其使用。原因可能如下:
          內(nèi)存中加載的數(shù)據(jù)量過于龐大,如一次從數(shù)據(jù)庫取出過多數(shù)據(jù)
          代碼中存在死循環(huán)或循環(huán)產(chǎn)生過多重復(fù)的對(duì)象實(shí)體
          遞歸調(diào)用太深,導(dǎo)致堆棧溢出等
          內(nèi)存泄漏最終導(dǎo)致內(nèi)存溢出
          內(nèi)存泄漏是指向系統(tǒng)申請(qǐng)分配內(nèi)存進(jìn)行使用(new),但是用完后不歸還(delete),導(dǎo)致占用有效內(nèi)存。常見的幾種情況:
          (1) 在類的構(gòu)造函數(shù)和析構(gòu)函數(shù)中沒有匹配的調(diào)用new和delete函數(shù)
          兩種情況下會(huì)出現(xiàn)這種內(nèi)存泄露:一是在堆里創(chuàng)建了對(duì)象占用了內(nèi)存,但是沒有顯示地釋放對(duì)象占用的內(nèi)存;二是在類的構(gòu)造函數(shù)中動(dòng)態(tài)的分配了內(nèi)存,但是在析構(gòu) 函數(shù)中沒有釋放內(nèi)存或者沒有正確的釋放內(nèi)存</br>
          (2) 在釋放對(duì)象數(shù)組時(shí)在delete中沒有使用方括號(hào)
          方括號(hào)是告訴編譯器這個(gè)指針指向的是一個(gè)對(duì)象數(shù)組,同時(shí)也告訴編譯器正確的對(duì)象地址值病調(diào)用對(duì)象的析構(gòu)函數(shù),如果沒有方括號(hào),那么這個(gè)指針就被默認(rèn)為只指向一個(gè)對(duì)象,對(duì)象數(shù)組中的其他對(duì)象的析構(gòu)函數(shù)就不會(huì)被調(diào)用,結(jié)果造成了內(nèi)存泄露。</br>
          (3)沒有將基類的析構(gòu)函數(shù)定義為虛函數(shù)
          當(dāng)基類指針指向子類對(duì)象時(shí),如果基類的析構(gòu)函數(shù)不是virtual,那么子類的析構(gòu)函數(shù)將不會(huì)被調(diào)用,子類的資源沒有正確是釋放,因此造成內(nèi)存泄露</br>

          參考鏈接:https://blog.csdn.net/hyqwmxsh/article/details/52813307

          緩沖區(qū)溢出(棧溢出)</br>
          程序?yàn)榱伺R時(shí)存取數(shù)據(jù)的需要,一般會(huì)分配一些內(nèi)存空間稱為緩沖區(qū)。如果向緩沖區(qū)中寫入緩沖區(qū)無法容納的數(shù)據(jù),機(jī)會(huì)造成緩沖區(qū)以外的存儲(chǔ)單元被改寫,稱為緩沖區(qū)溢出。而棧溢出是緩沖區(qū)溢出的一種,原理也是相同的。分為上溢出和下溢出。其中,上溢出是指棧滿而又向其增加新的數(shù)據(jù),導(dǎo)致數(shù)據(jù)溢出;下溢出是指空棧而又進(jìn)行刪除操作等,導(dǎo)致空間溢出。</br>

          面試題 6:sizeof 和 strlen 的區(qū)別
          sizeof 和 strlen 有以下區(qū)別:
          1 sizeof 是一個(gè)操作符,strlen 是庫函數(shù)。
          2 sizeof 的參數(shù)可以是數(shù)據(jù)的類型,也可以是變量,而 strlen 只能以結(jié)尾為‘\0‘的字符串作參數(shù)。
          3 編譯器在編譯時(shí)就計(jì)算出了 sizeof 的結(jié)果。而 strlen 函數(shù)必須在運(yùn)行時(shí)才能計(jì)算出來。并且 sizeof 計(jì)算的是數(shù)據(jù)類型占內(nèi)存的大小,而 strlen 計(jì)算的是字符串實(shí)際的長度。
          4 數(shù)組做 sizeof 的參數(shù)不退化,傳遞給 strlen 就退化為指針了。
          注意:有些是操作符看起來像是函數(shù),而有些函數(shù)名看起來又像操作符,這類容易混淆的名稱一定要加以區(qū)分,否則遇到數(shù)組名這類特殊數(shù)據(jù)類型作參數(shù)時(shí)就很容易出錯(cuò)。最容易混淆為函數(shù)的操作符就是 sizeof。


          面試題 7:C中的 malloc 和C++中的 new 有什么區(qū)別malloc 和 new 有以下不同:
          (1) new、delete 是操作符,可以重載,只能在 C++中使用。
          (2) malloc、free 是函數(shù),可以覆蓋,C、C++中都可以使用。
          (3) new 可以調(diào)用對(duì)象的構(gòu)造函數(shù),對(duì)應(yīng)的 delete 調(diào)用相應(yīng)的析構(gòu)函數(shù)。
          (4) malloc 僅僅分配內(nèi)存,free 僅僅回收內(nèi)存,并不執(zhí)行構(gòu)造和析構(gòu)函數(shù)
          (5) new、delete 返回的是某種數(shù)據(jù)類型指針,malloc、free 返回的是 void 指針。
          注意:malloc 申請(qǐng)的內(nèi)存空間要用 free 釋放,而 new 申請(qǐng)的內(nèi)存空間要用 delete 釋放,不要混用。因?yàn)閮烧邔?shí)現(xiàn)的機(jī)理不同。

          面試題 8:寫一個(gè)“標(biāo)準(zhǔn)”宏 MIN
          #define min(a,b)((a)<=(b)?(a):(b))
          注意:在調(diào)用時(shí)一定要注意這個(gè)宏定義的副作用,如下調(diào)用:
          ((++*p)<=(x)?(++*p):(x)。
          p 指針就自加了兩次,違背了 MIN 的本意。

          9:一個(gè)指針可以是 volatile 嗎
          可以,因?yàn)橹羔樅推胀ㄗ兞恳粯?,有時(shí)也有變化程序的不可控性。常見例:子中斷服務(wù)子程序修改一個(gè)指向一個(gè) buffer 的指針時(shí),必須用 volatile 來修飾這個(gè)指針。
          說明:指針是一種普通的變量,從訪問上沒有什么不同于其他變量的特性。其保存的數(shù)值是個(gè)整型數(shù)據(jù),和整型變量不同的是,這個(gè)整型數(shù)據(jù)指向的是一段內(nèi)存地址。

          面試題 10:a 和&a 有什么區(qū)別
          請(qǐng)寫出以下代碼的打印結(jié)果,主要目的是考察 a 和&a 的區(qū)別。
          #include<stdio.h> 
          void main( void ) 

            int a[5]={1,2,3,4,5}; 
            int *ptr=(int *)(&a+1); 
           printf("%d,%d",*(a+1),*(ptr-1));   return

          輸出結(jié)果:2,5。
          注意:數(shù)組名 a 可以作數(shù)組的首地址,而&a 是數(shù)組的指針。思考,將原式的 int *ptr=(int *)(&a+1); 改為 int *ptr=(int *)(a+1);時(shí)輸出結(jié)果將是什么呢?

          面試題 11:簡述 C、C++程序編譯的內(nèi)存分配情況
          C、C++中內(nèi)存分配方式可以分為三種:
          (1) 從靜態(tài)存儲(chǔ)區(qū)域分配:
          內(nèi)存在程序編譯時(shí)就已經(jīng)分配好,這塊內(nèi)存在程序的整個(gè)運(yùn)行期間都存在。速度快、不容易出錯(cuò),因?yàn)橛邢到y(tǒng)會(huì)善后。例如全局變量,static 變量等。
          (2) 在棧上分配:
          在執(zhí)行函數(shù)時(shí),函數(shù)內(nèi)局部變量的存儲(chǔ)單元都在棧上創(chuàng)建,函數(shù)執(zhí)行結(jié)束時(shí)這些存儲(chǔ)單元自動(dòng)被釋放。棧內(nèi)存分配運(yùn)算內(nèi)置于處理器的指令集中,效率很高,但是分配的內(nèi)存容量有限。
          (3) 從堆上分配:
          即動(dòng)態(tài)內(nèi)存分配。程序在運(yùn)行的時(shí)候用 malloc 或 new 申請(qǐng)任意大小的內(nèi)存,程序員自己負(fù)責(zé)在何時(shí)用 free 或 delete 釋放內(nèi)存。動(dòng)態(tài)內(nèi)存的生存期由程序員決定,使用非常靈活。如果在堆上分配了空間,就有責(zé)任回收它,否則運(yùn)行的程序會(huì)出現(xiàn)內(nèi)存泄漏,另外頻繁地分配和釋放不同大小的堆空間將會(huì)產(chǎn)生堆內(nèi)碎塊。
          一個(gè) C、C++程序編譯時(shí)內(nèi)存分為 5 大存儲(chǔ)區(qū):堆區(qū)、棧區(qū)、全局區(qū)、文字常量區(qū)、程序代碼區(qū)。

          12:STL中map和set的原理(關(guān)聯(lián)式容器)
          map和set的底層實(shí)現(xiàn)主要通過紅黑樹來實(shí)現(xiàn)
          紅黑樹是一種特殊的二叉查找樹
          1)每個(gè)節(jié)點(diǎn)或者是黑色,或者是紅色
          2)根節(jié)點(diǎn)是黑色
          3) 每個(gè)葉子節(jié)點(diǎn)(NIL)是黑色。[注意:這里葉子節(jié)點(diǎn),是指為空(NIL或NULL)的葉子節(jié)點(diǎn)!]
          4)如果一個(gè)節(jié)點(diǎn)是紅色的,則它的子節(jié)點(diǎn)必須是黑色的
          5)從一個(gè)節(jié)點(diǎn)到該節(jié)點(diǎn)的子孫節(jié)點(diǎn)的所有路徑上包含相同數(shù)目的黑節(jié)點(diǎn)。
          特性4)5)決定了沒有一條路徑會(huì)比其他路徑長出2倍,因此紅黑樹是接近平衡的二叉樹。

          面試題 13:C++文件編譯與執(zhí)行的四個(gè)階段
          1)預(yù)處理:根據(jù)文件中的預(yù)處理指令來修改源文件的內(nèi)容
          2)編譯:編譯成匯編代碼
          3)匯編:把匯編代碼翻譯成目標(biāo)機(jī)器指令
          4)鏈接:鏈接目標(biāo)代碼生成可執(zhí)行程序

          面試題 14:面向?qū)ο蟮娜筇卣?/strong>
          面向?qū)ο蟮娜筇卣魇欠庋b性、繼承性和多態(tài)性:
          ? 封裝性:將客觀事物抽象成類,每個(gè)類對(duì)自身的數(shù)據(jù)和方法實(shí)行 protection(private, protected, public)。
          ? 繼承性:廣義的繼承有三種實(shí)現(xiàn)形式:實(shí)現(xiàn)繼承(使用基類的屬性和方法而無需額外編碼的能力)、可視繼承(子窗體使用父窗體的外觀和實(shí)現(xiàn)代碼)、接口繼承(僅使用屬性和方法,實(shí)現(xiàn)滯后到子類實(shí)現(xiàn))。
          ? 多態(tài)性:是將父類對(duì)象設(shè)置成為和一個(gè)或更多它的子對(duì)象相等的技術(shù)。用子類對(duì)象給父類對(duì)象賦值之后,父類對(duì)象就可以根據(jù)當(dāng)前賦值給它的子對(duì)象的特性以不同的方式運(yùn)作。
          說明:面向?qū)ο蟮娜齻€(gè)特征是實(shí)現(xiàn)面向?qū)ο蠹夹g(shù)的關(guān)鍵,每一個(gè)特征的相關(guān)技術(shù)都非常的復(fù)雜,程序員應(yīng)該多看、多練。

          面試題 15:C++的空類有哪些成員函數(shù)
          ? 缺省構(gòu)造函數(shù)。
          ? 缺省拷貝構(gòu)造函數(shù)。
          ? 缺省析構(gòu)函數(shù)。
          ? 缺省賦值運(yùn)算符。
          ? 缺省取址運(yùn)算符。
          ? 缺省取址運(yùn)算符 const。
          注意:有些書上只是簡單的介紹了前四個(gè)函數(shù)。沒有提及后面這兩個(gè)函數(shù)。但后面這兩個(gè)函數(shù)也是空類的默認(rèn)函數(shù)。另外需要注意的是,只有當(dāng)實(shí)際使用這些函數(shù)的時(shí)候,編譯器才會(huì)去定義它們。

          面試題 16:談?wù)勀銓?duì)拷貝構(gòu)造函數(shù)和賦值運(yùn)算符的認(rèn)識(shí)
          拷貝構(gòu)造函數(shù)和賦值運(yùn)算符重載有以下兩個(gè)不同之處:
          (1) 拷貝構(gòu)造函數(shù)生成新的類對(duì)象,而賦值運(yùn)算符不能。
          (2) 由于拷貝構(gòu)造函數(shù)是直接構(gòu)造一個(gè)新的類對(duì)象,所以在初始化這個(gè)對(duì)象之前不用檢驗(yàn)源對(duì)象是否和新建對(duì)象相同。而賦值運(yùn)算符則需要這個(gè)操作,另外賦值運(yùn)算中如果原來的對(duì)象中有內(nèi)存分配要先把內(nèi)存釋放掉
          注意:當(dāng)有類中有指針類型的成員變量時(shí),一定要重寫拷貝構(gòu)造函數(shù)和賦值運(yùn)算符,不要使用默認(rèn)的。

          面試題 17:STL中的vector的實(shí)現(xiàn),是怎么擴(kuò)容的?
          vector使用的注意點(diǎn)及其原因,頻繁對(duì)vector調(diào)用push_back()對(duì)性能的影響和原因。vector就是一個(gè)動(dòng)態(tài)增長的數(shù)組,里面有一個(gè)指針指向一片連續(xù)的空間,當(dāng)空間裝不下的時(shí)候,會(huì)申請(qǐng)一片更大的空間,將原來的數(shù)據(jù)拷貝過去,并釋放原來的舊空間。當(dāng)刪除的時(shí)候空間并不會(huì)被釋放,只是清空了里面的數(shù)據(jù)。對(duì)比array是靜態(tài)空間一旦配置了就不能改變大小。
          vector的動(dòng)態(tài)增加大小的時(shí)候,并不是在原有的空間上持續(xù)新的空間(無法保證原空間的后面還有可供配置的空間),而是以原大小的兩倍另外配置一塊較大的空間,然后將原內(nèi)容拷貝過來,并釋放原空間。在VS下是1.5倍擴(kuò)容,在GCC下是2倍擴(kuò)容。
          在原來空間不夠存儲(chǔ)新值時(shí),每次調(diào)用push_back方法都會(huì)重新分配新的空間以滿足新數(shù)據(jù)的添加操作。如果在程序中頻繁進(jìn)行這種操作,還是比較消耗性能的。

          面試題 18:用 C++設(shè)計(jì)一個(gè)不能被繼承的類
          template <typename T> class A 

            friend T; private: 
            A() {} 
            ~A() {} 
          }; 
           
          class B : virtual public A<B
          { public: 
            B() {} 
            ~B() {} 
          }; 
          class C : virtual public B 
          { public: 
            C() {} 
            ~C() {} 
          }; 
          void main( void ) 

           B b;  //C c; 
            return

          注意:構(gòu)造函數(shù)是繼承實(shí)現(xiàn)的關(guān)鍵,每次子類對(duì)象構(gòu)造時(shí),首先調(diào)用的是父類的構(gòu)造函數(shù),然后才是自己的。

          面試題 19:STL中unordered_map和map的區(qū)別
          map是STL中的一個(gè)關(guān)聯(lián)容器,提供鍵值對(duì)的數(shù)據(jù)管理。底層通過紅黑樹來實(shí)現(xiàn),實(shí)際上是二叉排序樹和非嚴(yán)格意義上的二叉平衡樹。所以在map內(nèi)部所有的數(shù)據(jù)都是有序的,且map的查詢、插入、刪除操作的時(shí)間復(fù)雜度都是O(logN)。
          unordered_map和map類似,都是存儲(chǔ)key-value對(duì),可以通過key快速索引到value,不同的是unordered_map不會(huì)根據(jù)key進(jìn)行排序。unordered_map底層是一個(gè)防冗余的哈希表,存儲(chǔ)時(shí)根據(jù)key的hash值判斷元素是否相同,即unoredered_map內(nèi)部是無序的。

          面試題 20:簡述類成員函數(shù)的重寫、重載和隱藏的區(qū)別
          (1)重寫和重載主要有以下幾點(diǎn)不同。
          ? 范圍的區(qū)別:被重寫的和重寫的函數(shù)在兩個(gè)類中,而重載和被重載的函數(shù)在同
          ? 參數(shù)的區(qū)別:被重寫函數(shù)和重寫函數(shù)的參數(shù)列表一定相同,而被重載函數(shù)和重載函數(shù)的參數(shù)列表一定不同。
          ? virtual 的區(qū)別:重寫的基類中被重寫的函數(shù)必須要有 virtual 修飾,而重載函數(shù)和被重載函數(shù)可以被 virtual 修飾,也可以沒有。
          (2)隱藏和重寫、重載有以下幾點(diǎn)不同。
          ? 與重載的范圍不同:和重寫一樣,隱藏函數(shù)和被隱藏函數(shù)不在同一個(gè)類中。
          ? 參數(shù)的區(qū)別:隱藏函數(shù)和被隱藏的函數(shù)的參數(shù)列表可以相同,也可不同,但是函數(shù)名肯定要相同。當(dāng)參數(shù)不相同時(shí),無論基類中的參數(shù)是否被 virtual 修飾,基類的函數(shù)都是被隱藏,而不是被重寫。
          說明:雖然重載和覆蓋都是實(shí)現(xiàn)多態(tài)的基礎(chǔ),但是兩者實(shí)現(xiàn)的技術(shù)完全不相同,達(dá)到的目的也是完全不同的,覆蓋是動(dòng)態(tài)態(tài)綁定的多態(tài),而重載是靜態(tài)綁定的多態(tài)。

          面試題 21:簡述多態(tài)實(shí)現(xiàn)的原理
          編譯器發(fā)現(xiàn)一個(gè)類中有虛函數(shù),便會(huì)立即為此類生成虛函數(shù)表 vtable。虛函數(shù)表的各表項(xiàng)為指向?qū)?yīng)虛函數(shù)的指針。編譯器還會(huì)在此類中隱含插入一個(gè)指針 vptr(對(duì) vc 編譯器來說,它插在類的第一個(gè)位置上)指向虛函數(shù)表。調(diào)用此類的構(gòu)造函數(shù)時(shí),在類的構(gòu)造函數(shù)中,編譯器會(huì)隱含執(zhí)行 vptr 與 vtable 的關(guān)聯(lián)代碼,將 vptr 指向?qū)?yīng)的 vtable,將類與此類的 vtable 聯(lián)系了起來。另外在調(diào)用類的構(gòu)造函數(shù)時(shí),指向基礎(chǔ)類的指針此時(shí)已經(jīng)變成指向具體的類的 this 指針,這樣依靠此 this 指針即可得到正確的 vtable,。
          如此才能真正與函數(shù)體進(jìn)行連接,這就是動(dòng)態(tài)聯(lián)編,實(shí)現(xiàn)多態(tài)的基本原理。
          注意:一定要區(qū)分虛函數(shù),純虛函數(shù)、虛擬繼承的關(guān)系和區(qū)別。牢記虛函數(shù)實(shí)現(xiàn)原理,因?yàn)槎鄳B(tài) C++面試的重要考點(diǎn)之一,而虛函數(shù)是實(shí)現(xiàn)多態(tài)的基礎(chǔ)。

          面試題 22:C++的內(nèi)存管理
          在C++中,內(nèi)存被分成五個(gè)區(qū):棧、堆、自由存儲(chǔ)區(qū)、靜態(tài)存儲(chǔ)區(qū)、常量區(qū)
          棧:存放函數(shù)的參數(shù)和局部變量,編譯器自動(dòng)分配和釋放
          堆:new關(guān)鍵字動(dòng)態(tài)分配的內(nèi)存,由程序員手動(dòng)進(jìn)行釋放,否則程序結(jié)束后,由操作系統(tǒng)自動(dòng)進(jìn)行回收
          自由存儲(chǔ)區(qū):由malloc分配的內(nèi)存,和堆十分相似,由對(duì)應(yīng)的free進(jìn)行釋放
          全局/靜態(tài)存儲(chǔ)區(qū):存放全局變量和靜態(tài)變量
          常量區(qū):存放常量,不允許被修改

          面試題 23:簡述一下C++編譯過程

          面試題 24:構(gòu)造函數(shù)為什么一般不定義為虛函數(shù)?而析構(gòu)函數(shù)一般寫成虛函數(shù)的原因 ?
          隊(duì)列和棧都是線性存儲(chǔ)結(jié)構(gòu),但是兩者的插入和刪除數(shù)據(jù)的操作不同,隊(duì)列是“先進(jìn)先出”,棧是 “后進(jìn)先出”。
          注意:區(qū)別棧區(qū)和堆區(qū)。堆區(qū)的存取是“順序隨意”,而棧區(qū)是“后進(jìn)先出”。棧由編譯器自動(dòng)分配釋放 ,存放函數(shù)的參數(shù)值,局部變量的值等。其操作方式類似于數(shù)據(jù)結(jié)構(gòu)中的棧。堆一般由程序員分配釋放, 若程序員不釋放,程序結(jié)束時(shí)可能由 OS 回收。分配方式類似于鏈表。
          1、構(gòu)造函數(shù)不能聲明為虛函數(shù)
          1)因?yàn)閯?chuàng)建一個(gè)對(duì)象時(shí)需要確定對(duì)象的類型,而虛函數(shù)是在運(yùn)行時(shí)確定其類型的。而在構(gòu)造一個(gè)對(duì)象時(shí),由于對(duì)象還未創(chuàng)建成功,編譯器無法知道對(duì)象的實(shí)際類型,是類本身還是類的派生類等等
          2)虛函數(shù)的調(diào)用需要虛函數(shù)表指針,而該指針存放在對(duì)象的內(nèi)存空間中;若構(gòu)造函數(shù)聲明為虛函數(shù),那么由于對(duì)象還未創(chuàng)建,還沒有內(nèi)存空間,更沒有虛函數(shù)表地址用來調(diào)用虛函數(shù)即構(gòu)造函數(shù)了
          2、析構(gòu)函數(shù)最好聲明為虛函數(shù)
          首先析構(gòu)函數(shù)可以為虛函數(shù),當(dāng)析構(gòu)一個(gè)指向派生類的基類指針時(shí),最好將基類的析構(gòu)函數(shù)聲明為虛函數(shù),否則可以存在內(nèi)存泄露的問題。
          如果析構(gòu)函數(shù)不被聲明成虛函數(shù),則編譯器實(shí)施靜態(tài)綁定,在刪除指向派生類的基類指針時(shí),只會(huì)調(diào)用基類的析構(gòu)函數(shù)而不調(diào)用派生類析構(gòu)函數(shù),這樣就會(huì)造成派生類對(duì)象析構(gòu)不完全。1、構(gòu)造函數(shù)不能聲明為虛函數(shù)
          1)因?yàn)閯?chuàng)建一個(gè)對(duì)象時(shí)需要確定對(duì)象的類型,而虛函數(shù)是在運(yùn)行時(shí)確定其類型的。而在構(gòu)造一個(gè)對(duì)象時(shí),由于對(duì)象還未創(chuàng)建成功,編譯器無法知道對(duì)象的實(shí)際類型,是類本身還是類的派生類等等
          2)虛函數(shù)的調(diào)用需要虛函數(shù)表指針,而該指針存放在對(duì)象的內(nèi)存空間中;若構(gòu)造函數(shù)聲明為虛函數(shù),那么由于對(duì)象還未創(chuàng)建,還沒有內(nèi)存空間,更沒有虛函數(shù)表地址用來調(diào)用虛函數(shù)即構(gòu)造函數(shù)了
          2、析構(gòu)函數(shù)最好聲明為虛函數(shù)
          首先析構(gòu)函數(shù)可以為虛函數(shù),當(dāng)析構(gòu)一個(gè)指向派生類的基類指針時(shí),最好將基類的析構(gòu)函數(shù)聲明為虛函數(shù),否則可以存在內(nèi)存泄露的問題。
          如果析構(gòu)函數(shù)不被聲明成虛函數(shù),則編譯器實(shí)施靜態(tài)綁定,在刪除指向派生類的基類指針時(shí),只會(huì)調(diào)用基類的析構(gòu)函數(shù)而不調(diào)用派生類析構(gòu)函數(shù),這樣就會(huì)造成派生類對(duì)象析構(gòu)不完全。它與本題中的堆和棧是兩回事。堆棧只是一種數(shù)據(jù)結(jié)構(gòu),而堆區(qū)和棧區(qū)是程序的不同內(nèi)存存儲(chǔ)區(qū)域。

          面試題 25:簡述大端、小端模式
          大端模式,是指數(shù)據(jù)的高字節(jié)保存在內(nèi)存的低地址。
          小端模式,是指數(shù)據(jù)的高字節(jié)保存在內(nèi)存的高地址中
          使用程序判斷大小端:
              int a=1;
              char *p=(char *)&a;
              if(*p==1) printf("小端\n");
              else      printf("大端\n");


          面試題 26:.i++是否為原子操作?
          不是。操作系統(tǒng)原子操作是不可分割的,在執(zhí)行完畢不會(huì)被任何其它任務(wù)或事件中斷,分為兩種情況(兩種都應(yīng)該滿足)
          (1) 在單線程中, 能夠在單條指令中完成的操作都可以認(rèn)為是" 原子操作",因?yàn)橹袛嘀荒馨l(fā)生于指令之間。
          (2) 在多線程中,不能被其它進(jìn)程(線程)打斷的操作就叫原子操作。i++分為三個(gè)階段:
          內(nèi)存到寄存器
          寄存器自增
          寫回內(nèi)存
          這三個(gè)階段中間都可以被中斷分離開.


          面試題 27:指針與引用的區(qū)別
          (1)指針只是一個(gè)變量,只不過這個(gè)變量存儲(chǔ)的是一個(gè)地址;而引用跟原來的變量實(shí)質(zhì)上是同一個(gè)東西,只不過是原變量的一個(gè)別名而已,不占用內(nèi)存空間。(2)引用必須在定義的時(shí)候初始化,而且初始化后就不能再改變;而指針不必在定義的時(shí)候初始化,初始化后可以改變。(3)指針可以為空,但引用不能為空(這就意味著我們拿到一個(gè)引用的時(shí)候,是不需要判斷引用是否為空的,而拿到一個(gè)指針的時(shí)候,我們則需要判斷它是否為空。這點(diǎn)經(jīng)常在判斷函數(shù)參數(shù)是否有效的時(shí)候使用。) (4)“sizeof 引用" = 指向變量的大小 , "sizeof 指針"= 指針本身的大小 (5)指針可以有多級(jí),而引用只能是一級(jí)

          面試題 28:new與malloc的區(qū)別
          (1)malloc與free是C++/C語言的標(biāo)準(zhǔn)庫函數(shù),new/delete是C++的運(yùn)算符。它們都可用于申請(qǐng)動(dòng)態(tài)內(nèi)存和釋放內(nèi)存。
          (2)對(duì)于非內(nèi)部數(shù)據(jù)類型的對(duì)象而言,光用malloc/free無法滿足動(dòng)態(tài)對(duì)象的要求。對(duì)象在創(chuàng)建的同時(shí)要自動(dòng)執(zhí)行構(gòu)造函數(shù),對(duì)象在消亡之前要自動(dòng)執(zhí)行析構(gòu)函數(shù)。
          (3)new可以認(rèn)為是malloc加構(gòu)造函數(shù)的執(zhí)行。new出來的指針是直接帶類型信息的。而malloc返回的都是void指針。

          面試題 29:寫一個(gè)“標(biāo)準(zhǔn)”宏 MIN
          寫一個(gè)“標(biāo)準(zhǔn)”宏 MIN,這個(gè)宏輸入兩個(gè)參數(shù)并且返回較小的一個(gè)。
          【答案】
          #define min(a,b)((a)<=(b)?(a):(b))
          注意:在調(diào)用時(shí)一定要注意這個(gè)宏定義的副作用,如下調(diào)用:
          ((++*p)<=(x)?(++*p):(x)。
          p 指針就自加了兩次,違背了 MIN 的本意。

          面試題 30:typedef 和 define 有什么區(qū)別
          (1) 用法不同:typedef 用來定義一種數(shù)據(jù)類型的別名,增強(qiáng)程序的可讀性。define 主要用來定義常量,以及書寫復(fù)雜使用頻繁的宏。
          (2) 執(zhí)行時(shí)間不同:typedef 是編譯過程的一部分,有類型檢查的功能。define 是宏定義,是預(yù)編譯的部分,其發(fā)生在編譯之前,只是簡單的進(jìn)行字符串的替換,不進(jìn)行類型的檢查。
          (3) 作用域不同:typedef 有作用域限定。define 不受作用域約束,只要是在 define 聲明后的引用都是正確的。(4) 對(duì)指針的操作不同:typedef 和 define 定義的指針時(shí)有很大的區(qū)別。
          注意:typedef 定義是語句,因?yàn)榫湮惨由戏痔?hào)。而 define 不是語句,千萬不能在句尾加分號(hào)。

          面試題 31:關(guān)鍵字 const的作用
          (1)定義變量為只讀變量,不可修改
          (2)修飾函數(shù)的參數(shù)和返回值(后者應(yīng)用比較少,一般為值傳遞)
          (3)const成員函數(shù)(只需要在成員函數(shù)參數(shù)列表后加上關(guān)鍵字const,如char get() const;)可以訪問const成員變量和非const成員變量,但不能修改任何變量。在聲明一個(gè)成員函數(shù)時(shí),若該成員函數(shù)并不對(duì)數(shù)據(jù)成員進(jìn)行修改操作,應(yīng)盡可能將該成員函數(shù)聲明為const成員函數(shù)。
          (4)const對(duì)象只能訪問const成員函數(shù),而非const對(duì)象可以訪問任意的成員函數(shù),包括const成員函數(shù).即對(duì)于class A,有const A a;那么a只能訪問A的const成員函數(shù)。而對(duì)于:A b;b可以訪問任何成員函數(shù)。
          (5)使用const關(guān)鍵字修飾的變量,一定要對(duì)變量進(jìn)行初始化

          面試題 32:關(guān)鍵字static的作用
          1)函數(shù)體內(nèi):static 修飾的局部變量作用范圍為該函數(shù)體,不同于auto變量,其內(nèi)存只被分配一次,因此其值在下次調(diào)用的時(shí)候維持了上次的值
          2)模塊內(nèi):static修飾全局變量或全局函數(shù),可以被模塊內(nèi)的所有函數(shù)訪問,但是不能被模塊外的其他函數(shù)訪問,使用范圍限制在聲明它的模塊內(nèi)
          3)類中:修飾成員變量,表示該變量屬于整個(gè)類所有,對(duì)類的所有對(duì)象只有一份拷貝
          4)類中:修飾成員函數(shù),表示該函數(shù)屬于整個(gè)類所有,不接受this指針,只能訪問類中的static成員變量
          注意和const的區(qū)別?。?!const強(qiáng)調(diào)值不能被修改,而static強(qiáng)調(diào)唯一的拷貝,對(duì)所有類的對(duì)象

          面試題 33:extern關(guān)鍵字的作用
          extern置于變量或函數(shù)前,用于標(biāo)示變量或函數(shù)的定義在別的文件中,提示編譯器遇到此變量和函數(shù)時(shí)在其他模塊中尋找其定義。它只要有兩個(gè)作用:
          (1)當(dāng)它與“C”一起連用的時(shí)候,如:extern "C" void fun(int a,int b);則告訴編譯器在編譯fun這個(gè)函數(shù)時(shí)候按著C的規(guī)矩去翻譯,而不是C++的(這與C++的重載有關(guān),C++語言支持函數(shù)重載,C語言不支持函數(shù)重載,函數(shù)被C++編譯器編譯后在庫中的名字與C語言的不同)
          (2)當(dāng)extern不與“C”在一起修飾變量或函數(shù)時(shí),如:extern int g_Int;它的作用就是聲明函數(shù)或全局變量的作用范圍的關(guān)鍵字,其聲明的函數(shù)和變量可以在本模塊或其他模塊中使用。記住它是一個(gè)聲明不是定義!也就是說B模塊(編譯單元)要是引用模塊(編譯單元)A中定義的全局變量或函數(shù)時(shí),它只要包含A模塊的頭文件即可,在編譯階段,模塊B雖然找不到該函數(shù)或變量,但它不會(huì)報(bào)錯(cuò),它會(huì)在連接時(shí)從模塊A生成的目標(biāo)代碼中找到此函數(shù)。

          面試題 34:流操作符重載為什么返回引用
          在程序中,流操作符>>和<<經(jīng)常連續(xù)使用。因此這兩個(gè)操作符的返回值應(yīng)該是一個(gè)仍舊支持這兩個(gè)操作符的流引用。其他的數(shù)據(jù)類型都無法做到這一點(diǎn)。
          注意:除了在賦值操作符和流操作符之外的其他的一些操作符中,如+、-、*、/等卻千萬不能返回引用。因?yàn)檫@四個(gè)操作符的對(duì)象都是右值,因此,它們必須構(gòu)造一個(gè)對(duì)象作為返回值。

          面試題 35:什么情況下會(huì)調(diào)用拷貝構(gòu)造函數(shù)(三種情況)
          系統(tǒng)自動(dòng)生成的構(gòu)造函數(shù):普通構(gòu)造函數(shù)和拷貝構(gòu)造函數(shù) (在沒有定義對(duì)應(yīng)的構(gòu)造函數(shù)的時(shí)候)
          生成一個(gè)實(shí)例化的對(duì)象會(huì)調(diào)用一次普通構(gòu)造函數(shù),而用一個(gè)對(duì)象去實(shí)例化一個(gè)新的對(duì)象所調(diào)用的就是拷貝構(gòu)造函數(shù)
          調(diào)用拷貝構(gòu)造函數(shù)的情形:
          1)用類的一個(gè)對(duì)象去初始化另一個(gè)對(duì)象的時(shí)候
          2)當(dāng)函數(shù)的參數(shù)是類的對(duì)象時(shí),就是值傳遞的時(shí)候,如果是引用傳遞則不會(huì)調(diào)用
          3)當(dāng)函數(shù)的返回值是類的對(duì)象或者引用的時(shí)候
          舉例:
          #include <iostream>
          #include <string>
           
          using namespace std;
           
          class A{
           private:
            int data;
           public:
            A(int i){ data = i;}  //自定義的構(gòu)造函數(shù)
            A(A && a);     //拷貝構(gòu)造函數(shù) 
            int getdata(){return data;} 
          };
          //拷貝構(gòu)造函數(shù) 
          A::A(A && a){
           data = a.data;
           cout <<"拷貝構(gòu)造函數(shù)執(zhí)行完畢"<<endl;
          }
          //參數(shù)是對(duì)象,值傳遞,調(diào)用拷貝構(gòu)造函數(shù)
          int getdata1(A a){
           return a.getdata();
          }
          //參數(shù)是引用,引用傳遞,不調(diào)用拷貝構(gòu)造函數(shù) 
          int getdata2(A &a){
           return a.getdata();

          //返回值是對(duì)象類型,會(huì)調(diào)用拷貝構(gòu)造函數(shù)
           A getA1(){
            A a(0);
            return a;
           } 
           //返回值是引用類型,會(huì)調(diào)用拷貝構(gòu)造函數(shù),因?yàn)楹瘮?shù)體內(nèi)生成的對(duì)象是臨時(shí)的,離開函數(shù)就消失
           A& getA2(){
            A a(0);
            return a;
           } 
           
           int main(){
              A a1(1);  
              A b1(a1);             //用a1初始化b1,調(diào)用拷貝構(gòu)造函數(shù)  
              A c1=a1;              //用a1初始化c1,調(diào)用拷貝構(gòu)造函數(shù)  
            
              int i=getdata1(a1);         //函數(shù)形參是類的對(duì)象,調(diào)用拷貝構(gòu)造函數(shù)  
              int j=getdata2(a1);       //函數(shù)形參類型是引用,不調(diào)用拷貝構(gòu)造函數(shù)  
            
              A d1=getA1();         //調(diào)用拷貝構(gòu)造函數(shù)  
              A e1=getA2();        //調(diào)用拷貝構(gòu)造函數(shù)  
            
              return 0;  
          }  

          面試題 36:類型安全以及C++中的類型轉(zhuǎn)換?
          類型安全很大程度上可以等價(jià)于內(nèi)存安全,類型安全的代碼不會(huì)試圖訪問自己沒被授權(quán)的內(nèi)存區(qū)域。C只在局部上下文中表現(xiàn)出類型安全,比如試圖從一種結(jié)構(gòu)體的指針轉(zhuǎn)換成另一種結(jié)構(gòu)體的指針時(shí),編譯器將會(huì)報(bào)告錯(cuò)誤,除非使用顯式類型轉(zhuǎn)換。然而,C中相當(dāng)多的操作是不安全的。
          四種類型轉(zhuǎn)換:
          static_cast <T*> (content)  靜態(tài)轉(zhuǎn)換.在編譯期間處理,可以實(shí)現(xiàn)C++中內(nèi)置基本數(shù)據(jù)類型之間的相互轉(zhuǎn)換。如果涉及到類的話,static_cast只能在有相互聯(lián)系的類型中進(jìn)行相互轉(zhuǎn)換,不一定包含虛函數(shù)。
          dynamic_cast<T*>(content) 動(dòng)態(tài)類型轉(zhuǎn)換;也是向下安全轉(zhuǎn)型;是在運(yùn)行的時(shí)候執(zhí)行;基類中一定要有虛函數(shù),否則編譯不通過。在類層次間進(jìn)行上行轉(zhuǎn)換時(shí)(如派生類指針轉(zhuǎn)為基類指針),dynamic_cast和static_cast的效果是一樣的。在進(jìn)行下行轉(zhuǎn)換時(shí)(如基類指針轉(zhuǎn)為派生類指針),dynamic_cast具有類型檢查的功能,比static_cast更安全。
          const_cast<T*>(content) 去常轉(zhuǎn)換;編譯時(shí)執(zhí)行;
          reinterpret_cast<T*>(content) 重解釋類型轉(zhuǎn)換;

          面試題 37:如何避免“野指針”
          “野指針”產(chǎn)生原因及解決辦法如下:
          (1) 指針變量聲明時(shí)沒有被初始化。解決辦法:指針聲明時(shí)初始化,可以是具體的地址值,也可讓它指向 NULL。
          (2) 指針 p 被 free 或者 delete 之后,沒有置為 NULL。解決辦法:指針指向的內(nèi)存空間被釋放后指針應(yīng)該指向 NULL。
          (3) 指針操作超越了變量的作用范圍。解決辦法:在變量的作用域結(jié)束前釋放掉變量的地址空間并且讓指針指向 NULL。注意:“野指針”的解決方法也是編程規(guī)范的基本原則,平時(shí)使用指針時(shí)一定要避免產(chǎn)生“野指針”,在使用指針前一定要檢驗(yàn)指針的合法性。

          面試題 38:typdef和define區(qū)別
          #define是預(yù)處理命令,在預(yù)處理是執(zhí)行簡單的替換,不做正確性的檢查
          typedef是在編譯時(shí)處理的,它是在自己的作用域內(nèi)給已經(jīng)存在的類型一個(gè)別名
          typedef    (int*)      pINT;#define    pINT2   int*
          效果相同?實(shí)則不同!實(shí)踐中見差別:pINT a,b;的效果同int *a; int *b;表示定義了兩個(gè)整型指針變量。而pINT2 a,b;的效果同int *a, b;表示定義了一個(gè)整型指針變量a和整型變量b。

          面試題 39:動(dòng)態(tài)綁定與靜態(tài)綁定
          (1)靜態(tài)綁定發(fā)生在編譯期,動(dòng)態(tài)綁定發(fā)生在運(yùn)行期;(2)對(duì)象的動(dòng)態(tài)類型可以更改,但是靜態(tài)類型無法更改;(3)要想實(shí)現(xiàn)動(dòng)態(tài),必須使用動(dòng)態(tài)綁定;(4)在繼承體系中只有虛函數(shù)使用的是動(dòng)態(tài)綁定,其他的全部是靜態(tài)綁定;(5)靜態(tài)多態(tài)是指通過模板技術(shù)或者函數(shù)重載技術(shù)實(shí)現(xiàn)的多態(tài),其在編譯器確定行為。(6)動(dòng)態(tài)多態(tài)是指通過虛函數(shù)技術(shù)實(shí)現(xiàn)在運(yùn)行期動(dòng)態(tài)綁定的技術(shù)
          動(dòng)態(tài)綁定:有一個(gè)基類,兩個(gè)派生類,基類有一個(gè)virtual函數(shù),兩個(gè)派生類都覆蓋了這個(gè)虛函數(shù)?,F(xiàn)在有一個(gè)基類的指針或者引用,當(dāng)該基類指針或者引用指向不同的派生類對(duì)象時(shí),調(diào)用該虛函數(shù),那么最終調(diào)用的是該被指向?qū)ο髮?duì)應(yīng)的派生類自己實(shí)現(xiàn)的虛函數(shù)。

          面試題 40:智能指針怎么實(shí)現(xiàn)?什么時(shí)候改變引用計(jì)數(shù)?
          (1)構(gòu)造函數(shù)中計(jì)數(shù)初始化為1;
          (2)拷貝構(gòu)造函數(shù)中計(jì)數(shù)值加1;
          (3)賦值運(yùn)算符中,左邊的對(duì)象引用計(jì)數(shù)減一,右邊的對(duì)象引用計(jì)數(shù)加一;
          (4)析構(gòu)函數(shù)中引用計(jì)數(shù)減一;
          (5)在賦值運(yùn)算符和析構(gòu)函數(shù)中,如果減一后為0,則調(diào)用delete釋放對(duì)象。

          面試題 41:棧溢出的原因以及解決方法
          1)函數(shù)調(diào)用層次過深,每調(diào)用一次,函數(shù)的參數(shù)、局部變量等信息就壓一次棧
          2)局部變量體積太大。
          解決辦法大致說來也有兩種:
          1> 增加棧內(nèi)存的數(shù)目;增加棧內(nèi)存方法如下,在vc6種依次選擇Project->Setting->Link,在Category中選擇output,在Reserve中輸入16進(jìn)制的棧內(nèi)存大小如:0x10000000
          2> 使用堆內(nèi)存;具體實(shí)現(xiàn)由很多種方法可以直接把數(shù)組定義改成指針,然后動(dòng)態(tài)申請(qǐng)內(nèi)存;也可以把局部變量變成全局變量,一個(gè)偷懶的辦法是直接在定義前邊加個(gè)static,呵呵,直接變成靜態(tài)變量(實(shí)質(zhì)就是全局變量)

          面試題 42:構(gòu)造函數(shù)能否為虛函數(shù)
          構(gòu)造函數(shù)不能是虛函數(shù)。而且不能在構(gòu)造函數(shù)中調(diào)用虛函數(shù),因?yàn)槟菢訉?shí)際執(zhí)行的是父類的對(duì)應(yīng)函數(shù),因?yàn)樽约哼€沒有構(gòu)造好。析構(gòu)函數(shù)可以是虛函數(shù),而且,在一個(gè)復(fù)雜類結(jié)構(gòu)中,這往往是必須的。
          析構(gòu)函數(shù)也可以是純虛函數(shù),但純虛析構(gòu)函數(shù)必須有定義體,因?yàn)槲鰳?gòu)函數(shù)的調(diào)用是在子類中隱含的。
          說明:虛函數(shù)的動(dòng)態(tài)綁定特性是實(shí)現(xiàn)重載的關(guān)鍵技術(shù),動(dòng)態(tài)綁定根據(jù)實(shí)際的調(diào)用情況查詢相應(yīng)類的虛函數(shù)表,調(diào)用相應(yīng)的虛函數(shù)。

          面試題 43:談?wù)勀銓?duì)面向?qū)ο蟮恼J(rèn)識(shí)
          所謂的面向?qū)ο缶褪菍⑽覀兊某绦蚰K化,對(duì)象化,把具體事物的特性屬性和通過這些屬性來實(shí)現(xiàn)一些動(dòng)作的具體方法放到一個(gè)類里面,這就是封裝。封裝是我們所說的面相對(duì)象編程的特征之一。除此之外還有繼承和多態(tài)。繼承有點(diǎn)類似與我們生物學(xué)上的遺傳,就是子類的一些特征是來源于父類的,兒子遺傳了父親或母親的一些性格,或者相貌,又或者是運(yùn)動(dòng)天賦。有點(diǎn)種瓜得瓜種豆得豆的意思。面向?qū)ο罄锏睦^承也就是父類的相關(guān)的屬性,可以被子類重復(fù)使用,子類不必再在自己的類里面重新定義一回,父類里有點(diǎn)我們只要拿過來用就好了。而對(duì)于自己類里面需要用到的新的屬性和方法,子類就可以自己來擴(kuò)展了。當(dāng)然,會(huì)出現(xiàn)一些特殊情況,就是我們?cè)谟幸恍┓椒ㄔ诟割愐呀?jīng)定義好了,但是子類我們自己再用的時(shí)候,發(fā)現(xiàn),其實(shí),我們的雖然都是計(jì)算工資的,但是普通員工的工資計(jì)算方法跟經(jīng)理的計(jì)算方法是不一樣的,所以這個(gè)時(shí)候,我們就不能直接調(diào)用父類的這個(gè)計(jì)算工資的方法了。這個(gè)時(shí)候我們就需要用到面向?qū)ο蟮牧硪粋€(gè)特性,多態(tài)。對(duì),就是多態(tài),我們要在子類里面把父類里面定義計(jì)算工資的方法在子類里面重新實(shí)現(xiàn)一遍。多態(tài)包含了重載和重寫。重寫很簡單就是把子類從父親類里繼承下來的方法重新寫一遍,這樣,父類里相同的方法就被覆蓋了,當(dāng)然啦,你還是可以通過super.CaculSalary方法來調(diào)用父類的工資計(jì)算方法。而重載就是類里面相同方法名,不同形參的情況,可以是形參類型不同或者形參個(gè)數(shù)不同,或者形參順序不同,但是不能使返回值類型不同。

          面試題 44:引用作為函數(shù)參數(shù)以及返回值的好處
          對(duì)比值傳遞,引用傳參的好處:
          1)在函數(shù)內(nèi)部可以對(duì)此參數(shù)進(jìn)行修改
          2)提高函數(shù)調(diào)用和運(yùn)行的效率(所以沒有了傳值和生成副本的時(shí)間和空間消耗)
          如果函數(shù)的參數(shù)實(shí)質(zhì)就是形參,不過這個(gè)形參的作用域只是在函數(shù)體內(nèi)部,也就是說實(shí)參和形參是兩個(gè)不同的東西,要想形參代替實(shí)參,肯定有一個(gè)值的傳遞。函數(shù)調(diào)用時(shí),值的傳遞機(jī)制是通過“形參=實(shí)參”來對(duì)形參賦值達(dá)到傳值目的,產(chǎn)生了一個(gè)實(shí)參的副本。即使函數(shù)內(nèi)部有對(duì)參數(shù)的修改,也只是針對(duì)形參,也就是那個(gè)副本,實(shí)參不會(huì)有任何更改。函數(shù)一旦結(jié)束,形參生命也宣告終結(jié),做出的修改一樣沒對(duì)任何變量產(chǎn)生影響。
          用引用作為返回值最大的好處就是在內(nèi)存中不產(chǎn)生被返回值的副本。
          但是有以下的限制:
          1)不能返回局部變量的引用。因?yàn)楹瘮?shù)返回以后局部變量就會(huì)被銷毀
          2)不能返回函數(shù)內(nèi)部new分配的內(nèi)存的引用。雖然不存在局部變量的被動(dòng)銷毀問題,可對(duì)于這種情況(返回函數(shù)內(nèi)部new分配內(nèi)存的引用),又面臨其它尷尬局面。例如,被函數(shù)返回的引用只是作為一 個(gè)臨時(shí)變量出現(xiàn),而沒有被賦予一個(gè)實(shí)際的變量,那么這個(gè)引用所指向的空間(由new分配)就無法釋放,造成memory leak
          3)可以返回類成員的引用,但是最好是const。因?yàn)槿绻渌麑?duì)象可以獲得該屬性的非常量的引用,那么對(duì)該屬性的單純賦值就會(huì)破壞業(yè)務(wù)規(guī)則的完整性。

          瀏覽 119
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  在线观看操屄视频网站 | 藤浦惠一区二区三区免费观看 | 国产经典三级在线 | 日本色管视频 | 无码精品一区二区免费 |