天天看點

C/C++經典面試50題(挑重點整理)2

面試題17:簡述類成員函數的重寫、重載和隐藏的差別

(1)重寫和重載主要有以下幾點不同。

範圍的差別:被重寫的和重寫的函數在兩個類中,而重載和被重載的函數在同一個類中。

參數的差別:被重寫函數和重寫函數的參數清單一定相同,而被重載函數和重載函數的參數清單一定不同。

virtual的差別:重寫的基類中被重寫的函數必須要有virtual修飾,而重載函數和被重載函數可以被virtual修飾,也可以沒有。

(2)隐藏和重寫、重載有以下幾點不同。

與重載的範圍不同:和重寫一樣,隐藏函數和被隐藏函數不在同一個類中。

參數的差別:隐藏函數和被隐藏的函數的參數清單可以相同,也可不同,但是函數名肯定要相同。當參數不相同時,無論基類中的參數是否被virtual修飾,基類的函數都是被隐藏,而不是被重寫。

說明:雖然重載和覆寫都是實作多态的基礎,但是兩者實作的技術完全不相同,達到的目的也是完全不同的,覆寫是動态态綁定的多态,而重載是靜态綁定的多态。

面試題18:簡述多态實作的原理

編譯器發現一個類中有虛函數,便會立即為此類生成虛函數表 vtable。虛函數表的各表項為指向對應虛函數的指針。編譯器還會在此類中隐含插入一個指針vptr(對vc編譯器來說,它插在類的第一個位置上)指向虛函數表。調用此類的構造函數時,在類的構造函數中,編譯器會隐含執行vptr與vtable的關聯代碼,将vptr指向對應的vtable,将類與此類的vtable聯系了起來。另外在調用類的構造函數時,指向基礎類的指針此時已經變成指向具體的類的this指針,這樣依靠此this指針即可得到正确的vtable。如此才能真正與函數體進行連接配接,這就是動态聯編,實作多态的基本原理。

注意:一定要區分虛函數,純虛函數、虛拟繼承的關系和差別。牢記虛函數實作原理,因為多态C++面試的重要考點之一,而虛函數是實作多态的基礎。

面試題19:連結清單和數組有什麼差別

數組和連結清單有以下幾點不同:

(1)存儲形式:數組是一塊連續的空間,聲明時就要确定長度。連結清單是一塊可不連續的動态空間,長度可變,每個結點要儲存相鄰結點指針。

(2)資料查找:數組的線性查找速度快,查找操作直接使用偏移位址。連結清單需要按順序檢索結點,效率低。

(3)資料插入或删除:連結清單可以快速插入和删除結點,而數組則可能需要大量資料移動。

(4)越界問題:連結清單不存在越界問題,數組有越界問題。

說明:在選擇數組或連結清單資料結構時,一定要根據實際需要進行選擇。數組便于查詢,連結清單便于插入删除。數組節省空間但是長度固定,連結清單雖然變長但是占了更多的存儲空間。

面試題 21:簡述隊列和棧的異同

隊列和棧都是線性存儲結構,但是兩者的插入和删除資料的操作不同,隊列是“先進先出”,棧是“後進先出”。

注意:差別棧區和堆區。堆區的存取是順序随意,而棧區是後進先出。棧由編譯器自動配置設定釋放 ,存放函數的參數值,局部變量的值等。其操作方式類似于資料結構中的棧。堆一般由程式員配置設定釋放, 若程式員不釋放,程式結束時可能由OS回收。配置設定方式類似于連結清單。

它與本題中的堆和棧是兩回事。堆棧隻是一種資料結構,而堆區和棧區是程式的不同記憶體存儲區域。在面試題9有講述。

面試題32:C++的引用和C語言的指針有什麼差別

指針和引用主要有以下差別:

(1)引用必須被初始化,但是不配置設定存儲空間。指針不聲明時初始化,在初始化的時候需要配置設定存儲空間。//引用未初始化,編譯器會報錯![referencesmust be initialized]

(2)引用初始化以後不能被改變,指針可以改變所指的對象。

(3)不存在指向空值的引用,但是存在指向空值的指針。

注意:引用作為函數參數時,會引發一定的問題,因為讓引用作參數,目的就是想改變這個引用所指向位址的内容,而函數調用時傳入的是實參,看不出函數的參數是正常變量,還是引用,是以可能會引發錯誤。是以使用時一定要小心謹慎。

面試題35:typedef和define有什麼差別

(1)用法不同:typedef用來定義一種資料類型的别名,增強程式的可讀性。define主要用來定義常量,以及書寫複雜使用頻繁的宏。

(2)執行時間不同:typedef是編譯過程的一部分,有類型檢查的功能。define是宏定義,是預編譯的部分,其發生在編譯之前,隻是簡單的進行字元串的替換,不進行類型的檢查。

(3)作用域不同:typedef有作用域限定。define不受作用域限制,隻要是在define聲明後的引用都是正确的。

(4)對指針的操作不同:typedef和define定義的指針時有很大的差別。

注意:typedef定義是語句,因為句尾要加上分号。而define不是語句,千萬不能在句尾加分号。

面試題36:關鍵字const是什麼

const用來定義一個隻讀(不能修改其值)的變量或對象。主要優點:便于類型檢查、同宏定義一樣可以友善地進行參數的修改和調整、節省空間,避免不必要的記憶體配置設定、可為函數重載提供參考。

const 應用表現在:常量定義;類的成員變量為常量;類的成員函數為常量(表示該函數不能修改成員變量的值);函數傳遞的時候參數為常量。

說明:const修飾函數參數,是一種程式設計規範的要求,便于閱讀,一看即知這個參數不能被改變,實作時不易出錯。

面試題37:static有什麼作用

static在C中主要用于定義全局靜态變量、定義局部靜态變量、定義靜态函數。在C++中新增了兩種作用:定義靜态資料成員、靜态函數成員。

注意:因為static定義的變量配置設定在靜态區,是以其定義的變量的預設值為0,普通變量的預設值為随機數,在定義指針變量時要特别注意。

面試題38:extern有什麼作用

extern辨別的變量或者函數聲明其定義在别的檔案中,提示編譯器遇到此變量和函數時在其它子產品中尋找其定義。

面試題40:簡述指針常量與常量指針差別

指針常量是指定義了一個指針,這個指針的值隻能在定義時初始化,其他地方不能改變。常量指針是指定義了一個指針,這個指針指向一個隻讀的對象,不能通過常量指針來改變這個對象的值。

指針常量強調的是指針的不可改變性,而常量指針強調的是指針對其所指對象的不可改變性。

注意:無論是指針常量還是常量指針,其最大的用途就是作為函數的形式參數,保證明參在被調用函數中的不可改變特性。

舉例如下:

int main()

{

      int ival =55;

      int jval =38;

      //pa為指向常量的指針,不能通過pa改變其指向的ival的值;但pa可以指向其他變量.[常量指針==指針指向的值為常量]

      const int *pa= &ival;

      //*pa =88;           //報錯:l-valuespecifies const object

      pa =&jval;

      cout <<*pa << endl;  //正确. 38

      //pb為常量,指向變量的指針,pb不能修改,但可以修改pb指向的值。[指針常量==指針本身是個常量]

      int* const pb= &ival;

      //     pb = &jval;

      //     cout << *pb << endl;  //l-value specifies const object

      *pb = 2012;

      cout <<*pb << "\t" << ival << endl; //2012 2012

      //pc針對上述兩種修改都不可以。

      const int*const pc = &ival;

      cout <<*pc << endl;      //2012

      return 0;

}

面試題41:數組名和指針的差別

請寫出以下代碼的列印結果:

void main(void)

      charstr[13]="Hello world!";

      char*pStr="Hello world!";

      cout<<sizeof(str)<<endl;  //13

      cout<<sizeof(pStr)<<endl;//4

      cout<<strlen(str)<<endl;  //12

      cout<<strlen(pStr)<<endl;//12

      return;

注意:一定要記得數組名并不是真正意義上的指針,它的内涵要比指針豐富的多。但是當數組名當做參數傳遞給函數後,其失去原來的含義,變作普通的指針。

另外要注意sizeof不是函數,隻是操作符。

面試題42:如何避免“野指針”

“野指針”産生原因及解決辦法如下:

(1)指針變量聲明時沒有被初始化。解決辦法:指針聲明時初始化,可以是具體的位址值,也可讓它指向NULL。

(2)指針p 被 free或者delete之後,沒有置為NULL。解決辦法:指針指向的記憶體空間被釋放後指針應該指向NULL。

(3)指針操作超越了變量的作用範圍。解決辦法:在變量的作用域結束前釋放掉變量的位址空間并且讓指針指向NULL。

注意:“野指針”的解決方法也是程式設計規範的基本原則,平時使用指針時一定要避免産生“野指針”,在使用指針前一定要檢驗指針的合法性。

面試題43:常引用有什麼作用

常引用的引入主要是為了避免使用變量的引用時,在不知情的情況下改變變量的值。常引用主要用于定義一個普通變量的隻讀屬性的别名、作為函數的傳入形參,避免實參在調用函數中被意外的改變。

說明:很多情況下,需要用常引用做形參,被引用對象等效于常對象,不能在函數中改變實參的值,這樣的好處是有較高的易讀性和較小的出錯率。

voidmain(void)

      int ival = 58;

      void refFun(const int& xval);

      refFun(ival);

      cout << ival << endl; //不加const會傳回59,加const會報錯!

voidrefFun(const int& xval)

      xval = xval +1; //l-value specifies constobject[報錯]

面試題45:簡述strcpy、sprintf與memcpy的差別

三者主要有以下不同之處:

(1)操作對象不同,strcpy的兩個操作對象均為字元串,sprintf的操作源對象可以是多種資料類型,目的操作對象是字元串,memcpy 的兩個對象就是兩個任意可操作的記憶體位址,并不限于何種資料類型。

(2)執行效率不同,memcpy最高,strcpy次之,sprintf的效率最低。

(3)實作功能不同,strcpy主要實作字元串變量間的拷貝,sprintf主要實作其他資料類型格式到字元串的轉化,memcpy主要是記憶體塊間的拷貝。

說明:strcpy、sprintf與memcpy都可以實作拷貝的功能,但是針對的對象不同,根據實際需求,來選擇合适的函數實作拷貝功能。

面試題46:用C編寫一個死循環程式

while(1)

{ }

說明:很多種途徑都可實作同一種功能,但是不同的方法時間和空間占用度不同,特别是對于嵌入式軟體,處理器速度比較慢,存儲空間較小,是以時間和空間優勢是選擇各種方法的首要考慮條件。

面試題49:構造函數能否為虛函數

構造函數不能是虛函數。而且不能在構造函數中調用虛函數,因為那樣實際執行的是父類的對應函數,因為自己還沒有構造好。

析構函數可以是虛函數,而且,在一個複雜類結構中,這往往是必須的。析構函數也可以是純虛函數,但純虛析構函數必須有定義體,因為析構函數的調用是在子類中隐含的。

說明:虛函數的動态綁定特性是實作重載的關鍵技術,動态綁定根據實際的調用情況查詢相應類的虛函數表,調用相應的虛函數。

class Base

public:

//     virtual Base(){} //會報錯:'inline' isthe only legal storage class for constructors

      virtual ~Base(){}

};

      Base objB;

      cout << endl;

面試題50:談談你對面向對象的認識

面向對象可以了解成對待每一個問題,都是首先要确定這個問題由幾個部分組成,而每一個部分其實就是一個對象。然後再分别設計這些對象,最後得到整個程式。傳統的程式設計多是基于功能的思想來進行考慮和設計的,而面向對象的程式設計則是基于對象的角度來考慮問題。這樣做能夠使得程式更加的簡潔清晰。

說明:程式設計中接觸最多的“面向對象程式設計技術”僅僅是面向對象技術中的一個組成部分。發揮面向對象技術的優勢是一個綜合的技術問題,不僅需要面向對象的分析,設計和程式設計技術,而且需要借助必要的模組化和開發工具。

      個人認為:可以從項目開發的角度(實踐)或面向對象的三大特性(繼承、封裝、多态)三點入手談認識。

————————————————

版權聲明:本文為CSDN部落客「銘毅天下」的原創文章,遵循CC 4.0 BY-SA版權協定,轉載請附上原文出處連結及本聲明。

原文連結:

https://blog.csdn.net/laoyang360/article/details/7800419

繼續閱讀