1. 程式人生 > >經典C++筆試題目100例,接近實際,值得一看!

經典C++筆試題目100例,接近實際,值得一看!

第一部分:C++與C語言的差異(1-18)

1、C 和 C++ 中 struct 有什麼區別?

Protection行為 能否定義函式
C 否,但可以有函式指標
C++ 可以,預設是private


2、C++中的 struct 和 class 有什麼區別?

【參考答案】從語法上講,class和struct做型別定義時只有兩點區別: 
(一)預設繼承許可權。如果不明確指定,來自class的繼承按照private繼承處理,來自struct的繼承按照public繼承處理; 
(二)成員的預設訪問許可權。class的成員預設是private許可權,struct預設是public許可權。 除了這兩點,class和struct基本就是一個東西。語法上沒有任何其它區別。



3、如何判斷一段程式是由C 編譯程式還是由C++編譯程式編譯的?
【標準答案】

#ifdef __cplusplus  

        cout<<“c++";  

#else  

        printf("c");  

#endif  

複製程式碼

4、 C和C++有什麼不同?

【參考答案】
從機制上:C是面向過程的(但C也可以編寫面向物件的程式);C++是面向物件的,提供了類。但是,C++編寫面向物件的程式比C容易。
從適用的方向:C適合要求程式碼體積小的,效率高的場合,如嵌入式;C++適合更上層的,複雜的; llinux核心大部分是C寫的,因為它是系統軟體,效率要求極高。


從名稱上也可以看出,C++比C多了+,說明C++是C的超集;那為什麼不叫C+而叫C++呢,是因為C++比C來說擴充的東西太多了,所以就在C後面放上兩個+;於是就成了C++。
C語言是結構化程式語言,C++是面向物件程式語言。 C++側重於物件而不是過程,側重於類的設計而不是邏輯的設計。

5、“引用”與指標的區別是什麼?

【參考答案】
指標通過某個指標變數指向一個物件後,對它所指向的變數間接操作。程式中使用指標,程式的可讀性差;
而引用本身就是目標變數的別名,對引用的操作就是對目標變數的操作。

6、虛擬函式

class A  {   

   virtual void func1();   

   void func2();   

} ;  

class B: class A {   

   void func1() {  

        cout < < "fun1 in class B" < < endl;  

    }   

    virtual void func2() {  

    cout < < "fun2 in class B" < < endl;  

    }   

}   

複製程式碼

A、A中的func1和B中的func2都是虛擬函式
B、A中的func1和B中的func2都不是虛擬函式. 
C、A中的func2是虛擬函式.,B中的func1不是虛擬函式. 
D、A中的func2不是虛擬函式,B中的func1是虛擬函式. 
【標準答案】A

7、int id[sizeof(unsigned long)]; 這個對嗎?為什麼?
【標準答案】正確 這個 sizeof是編譯時運算子,編譯時就確定了 可以看成和機器有關的常量。


8、某檔案中定義的靜態全域性變數(或稱靜態外部變數)其作用域是 () ?

A.只限某個函式  B.本檔案    
C.跨檔案 D.不限制作用域
【參考答案】B。靜態全域性變數則限制了其作用域, 即只在定義該變數的原始檔內有效, 在同一源程式的其它原始檔中不能使用它。
由於靜態全域性變數的作用域侷限於一個原始檔內,只能為該原始檔內的函式公用, 因此可以避免在其它原始檔中引起錯誤。

9、C++函式中值的傳遞方式有哪幾種?

【標準答案】C++函式的三種傳遞方式為:值傳遞、指標傳遞和引用傳遞。


10、對於一個頻繁使用的短小函式,在C語言中應用什麼實現,在C++中應用什麼實現?

【標準答案】C用巨集定義,C++用 inline


11、引用與指標有什麼區別?

【參考答案】  
1) 引用必須被初始化,指標不必。
2) 引用初始化以後不能被改變,指標可以改變所指的物件。
3) 不存在指向空值的引用,但是存在指向空值的指標


12、C++中 virtual 與 inline 的含義分別是什麼?

【參考答案】
在基類成員函式的宣告前加上virtual關鍵字,意味著將該成員函式宣告為虛擬函式。
inline與函式的定義體放在一起,使該函式稱為內聯。inline是一種用於實現的關鍵字,而不是用於宣告的關鍵字。
## 虛擬函式的特點;
如果希望派生類能夠重新定義基類的方法,則在基類中將該方法定義為虛方法,這樣可以啟用動態聯編。
## 行內函數的特點;
使用行內函數的目的是為了提高函式的執行效率。
行內函數體的程式碼不能過長,因為行內函數省去呼叫函式的時間是以程式碼膨脹為代價的。
行內函數不能包含迴圈語句,因為執行迴圈語句要比呼叫函式的開銷大。

13、VC 中,編譯工具條內的 Debug 與 Release 選項是什麼含義?

【參考答案】
Debug 通常稱為除錯版本,它包含除錯資訊,並且不作任何優化,便於程式設計師除錯程式。
Release 稱為釋出版本,它往往是進行了各種優化,使得程式在程式碼大小和執行速度上都是最優的,以便使用者很好地使用。
Debug 帶有大量的除錯程式碼,執行時需要相應的執行庫,釋出模式程式緊湊不含有除錯程式碼和資訊,直接可以執行(如果不需要執行庫)


14、函式 assert 的用法?

【參考答案】
斷言assert是僅在debug版本起作用的巨集,用於檢查“不應該“發生的情況。
程式設計師可以把assert看成一個在任何系統狀態下都可以安全使用的無害測試手段。


15、 const  與 #define 的比較 ,const有什麼優點?

【參考答案】
(1) const 常量有資料型別,而巨集常量沒有資料型別。編譯器可以對前者進行型別安全檢查。
  而對後者只進行字元替換,沒有型別安全檢查,並且在字元替換可能會產生意料不到的錯誤(邊際效應) 。
(2)有些整合化的除錯工具可以對 const 常量進行除錯,但是不能對巨集常量進行除錯。


16、請你談談引用和指標的區別。

【參考答案】
(1)引用被建立的同時必須被初始化(指標則可以在任何時候被初始化) 。 
(2)不能有 NULL 引用,引用必須與合法的儲存單元關聯(指標則可以是 NULL) 。 
(3)一旦引用被初始化,就不能改變引用的關係(指標則可以隨時改變所指的物件) 。


17、有了 malloc/free 為什麼還要 new/delete  ?

【參考答案】
malloc 與 free 是 C++/C 語言的標準庫函式,new/delete 是 C++的運算子。它們都可用於申請動態記憶體和釋放記憶體。 
對於非內部資料型別的物件而言,光用 maloc/free 無法滿足動態物件的要求。物件在建立的同時要自動執行建構函式,物件在消亡之前要自動執行解構函式。
由於malloc/free 是庫函式而不是運算子,不在編譯器控制權限之內,不能夠把執行建構函式和解構函式的任務強加於 malloc/free。
因此 C++語言需要一個能完成動態記憶體分配和初始化工作的運算子 new,以及一個能完成清理與釋放記憶體工作的運算子 delete。
注意 new/delete 不是庫函式。


18、如果在申請動態記憶體時找不到足夠大的記憶體塊,malloc 和 new 將返回 NULL 指標,宣告記憶體申請失敗。你是怎麼處理記憶體耗盡的?

【參考答案】
(1)判斷指標是否為 NULL,如果是則馬上用 return 語句終止本函式。
(2)判斷指標是否為 NULL,如果是則馬上用 exit(1) 終止整個程式的執行 
(3)為 new 和 malloc 設定異常處理函式。例如 Visual C++可以用_set_new_hander 函式為 new 設定使用者自己定義的異常處理函式,
也可以讓 malloc 享用與 new 相同的異常處理函式。

第二部分:資料型別、關鍵字(19-37)

19、C++是不是型別安全的?

【參考答案】不是。兩個不同型別的指標之間可以強制轉換(用reinterpret cast)。

20、const 符號常量;

(1)const char *p
(2)char const *p
(3)char * const p
說明上面三種描述的區別;

【參考答案】
(1) p是一個指向const char的指標,p是可以改變指向的,但是p指向的值是不能改變的;      
(2) p指向的恰好是一個指向const的char的普通指標;
(3) p是一個指標,這個指標是指向char的const指標。      
(1)和(2)的定義是一樣的。

21、用C++寫個程式,如何判斷一個作業系統是16位還是32位的?

【標準答案】
定義一個指標p,打印出sizeof(p),如果節後是4,則表示該作業系統是32位,列印結果是2,表示是16位。

22、用C++寫個程式,如何判斷一個作業系統是16位還是32位的?不能用 sizeof() 函式。

【參考答案】    

int a = ~0;

if(a > 65536) {

    cout<<"32 bit"<<endl;

} else {

    cout<<"16 bit"<<endl;

}

複製程式碼

23、識別函式或指標

void * ( * (*fp1)(int))[10]; 
float (*(* fp2)(int,int,int))(int);
int (* ( * fp3)())[10](); 
分別表示什麼意思?

【標準答案】                                                           
1、void * ( * (*fp1)(int))[10];  fp1是一個指標,指向一個函式,這個函式的引數為int型,函式的返回值是一個指標,這個指標指向一個數組,
這個陣列有10個元素,每個元素是一個void*型指標。
2、float (*(* fp2)(int,int,int))(int);  fp2是一個指標,指向一個函式,這個函式的引數為3個int型,函式的返回值是一個指標,這個指標指向一個函式,
這個函式的引數為int型,函式的返回值是float型。
3、int (* ( * fp3)())[10]();  fp3是一個指標,指向一個函式,這個函式的引數為空,函式的返回值是一個指標,這個指標指向一個數組,
這個陣列有10個元素,每個元素是一個指標,指向一個函式,這個函式的引數為空,函式的返回值是int型。                                                   

24、多型類中的虛擬函式表是 Compile-Time,還是 Run-Time 時建立的?

【標準答案】
虛擬函式表是在編譯期就建立了,各個虛擬函式這時被組織成了一個虛擬函式的入口地址的陣列.而物件的隱藏成員--虛擬函式表指標是
在執行期--也就是建構函式被呼叫時進行初始化的,這是實現多型的關鍵。

25、錯誤的轉義字元是?
A、'\091' 
B、'\\'
C、'\0' D.'\''
【標準答案】A

26、若陣列名作實參而指標變數作形參,函式呼叫實參傳給形參的是?

A、陣列的長度  B.陣列第一個元素的值
C、陣列所有元素的值
D、陣列第一個元素的地址
【標準答案】D

27、變數的指標含意是指變數的?

A.值    B.地址 C.儲存    D.名字
【標準答案】B

28、記憶體的分配方式有幾種?

【參考答案】
一、從靜態儲存區域分配。記憶體在程式編譯的時候就已經分配好,這塊記憶體在程式的整個執行期間都存在。例如全域性變數。
二、在棧上建立。在執行函式時,函式內區域性變數的儲存單元都可以在棧上建立,函式執行結束時這些儲存單元自動被釋放。棧記憶體分配運算內置於處理器的指令集中,效
率很高,但是分配的記憶體容量有限。
三、從堆上分配,亦稱動態記憶體分配。程式在執行的時候用malloc或new申請任意多少的記憶體,程式設計師自己負責在何時用free或delete釋放記憶體。動態記憶體的生存期由我們
決定,使用非常靈活,但問題也最多。


29、float a,b,c , 問等式 (a+b)+c==(b+a)+c 和 (a+b)+c==(a+c)+b 能否成立?

【參考答案】
兩者都不行。在比較float或double時,不能簡單地比較。由於計算誤差,相等的概率很低。應判斷兩數之差是否落在區間(-e,e)內。
這個e應比浮點數的精度大一個數量級。

30、全域性變數和區域性變數有什麼區別?是怎麼實現的?作業系統和編譯器是怎麼知道的? 

【參考答案】
生命週期不同:
全域性變數隨主程式建立和建立,隨主程式銷燬而銷燬;
區域性變數在區域性函式內部,甚至區域性迴圈體等內部存在,退出就不存在; 記憶體中分配在全域性資料
區。 

使用方式不同:
通過聲明後全域性變數程式的各個部分都可以用到;區域性變數只能在區域性使用;分配在棧區。
作業系統和編譯器通過記憶體分配的位置來知道的,全域性變數分配在全域性資料段並且在程式開始執行的時候被載入。區域性變數則分配在堆疊裡面 。

31、Heap 與 Stack 的差別

【參考答案】
Heap是堆,stack是棧。 Stack的空間由作業系統自動分配/釋放,Heap上的空間手動分配/釋放。
Stack空間有限,Heap是很大的自由儲存區 C中的malloc函式分配的記憶體空間即在堆上,C++中對應的是new操作符。
程式在編譯期對變數和函式分配記憶體都在棧上進行,且程式執行過程中函式呼叫時引數的傳遞也在棧上進行

32、In C++, what does "explicit" mean? what does "protected" mean? 

【標準答案】
C++中的 explicit 關鍵字用來修飾類的建構函式,表明該建構函式是顯式的,在某些情況下,我們要求類的使用者必須顯示呼叫類的建構函式時就需要使用 explicit,反之預設型別轉換可能會造成無法預期的問題。
protected 控制的是一個函式對一個類的成員(包括成員變數及成員方法)的訪問許可權。protected成員只有該類的成員函式及其派生類的成員函式可以訪問。

33、重複多次 fclose 一個開啟過一次的 FILE *fp 指標會有什麼結果,並請解釋。 
【參考答案】
考察點:導致檔案描述符結構中指標指向的記憶體被重複釋放,進而導致一些不可預期的異常。

34、為什麼陣列名作為引數,會改變陣列的內容,而其它型別如int卻不會改變變數的值?

【參考答案】
當陣列名作為引數時,傳遞的實際上是地址。
而其他型別如int作為引數時,由於函式引數值實質上是實參的一份拷貝,被調函式內部對形參的改變並不影響實參的值。

35、你覺得如果不使用常量,直接在程式中填寫數字或字串,將會有什麼麻煩? 

【參考答案】
(1)  程式的可讀性(可理解性)變差。程式設計師自己會忘記那些數字或字串是什麼意思,使用者則更加不知它們從何處來、表示什麼。 
(2)  在程式的很多地方輸入同樣的數字或字串,難保不發生書寫錯誤。 
(3)  如果要修改數字或字串,則會在很多地方改動,既麻煩又容易出錯。

36、為什麼需要使用堆,使用堆空間的原因?

【參考答案】
直到執行時才知道一個物件需要多少記憶體空間;不知道物件的生存期到底有多長。

37、 const關鍵字?有哪些作用?

【參考答案】
const關鍵字至少有下列n個作用:
(1)欲阻止一個變數被改變,可以使用const關鍵字。在定義該const變數時,通常需要對它進行初始化,因為以後就沒有機會再去改變它了;
(2)對指標來說,可以指定指標本身為const,也可以指定指標所指的資料為const,或二者同時指定為const;
(3)在一個函式宣告中,const可以修飾形參,表明它是一個輸入引數,在函式內部不能改變其值;
(4)對於類的成員函式,若指定其為const型別,則表明其是一個常函式,不能修改類的成員變數;
(5)對於類的成員函式,有時候必須指定其返回值為const型別,以使得其返回值不為“左值”。
注: 這個題可以考查面試者對程式設計知識的掌握程度是初級、中級還是比較深入,沒有一定的知識廣度和深度,不可能對這個問題給出全面的解答。大多數人只能回答出 static 和 const 關鍵字的部分功能。

第三部分:C++面向物件的特性(38-61)

38、是不是一個父類寫了一個virtual 函式,如果子類覆蓋它的函式不加virtual ,也能實現多型?

【參考答案】
virtual修飾符會被隱形繼承的。virtual可加可不加。子類的空間裡有父類的所有變數(static除外)。同一個函式只存在一個實體(inline除外)。子類覆蓋它的函式不加virtual ,也能
實現多型。在子類的空間裡,有父類的私有變數。私有變數不能直接訪問。

39、面向物件的三個基本特徵,並簡單敘述之?

【參考答案】                                                                     
1. 封裝:將客觀事物抽象成類,每個類對自身的資料和方法實行protection(private, protected, public)                  
2. 繼承:廣義的繼承有三種實現形式:
實現繼承(指使用基類的屬性和方法而無需額外編碼的能力)、
可視繼承(子窗體使用父窗體的外觀和實現程式碼)、
介面繼承(僅使用屬性和方法,實現滯後到子類實現)。
前兩種(類繼承)和後一種(物件組合=>介面繼承以及純虛擬函式)構成了功能複用的兩種方式。                                 
3. 多型:是將父物件設定成為和一個或更多的與他的子物件相等的技術,賦值之後,父物件就可以根據當前賦值給它的子物件的特性以不同的方式運作。
簡單的說,就是一句話:允許將子類型別的指標賦值給父類型別的指標。

40、過載(overload)、重寫(override,有的書也叫做“覆蓋”)、重定義(redefinition)的區別?

【標準答案】
過載    同一名字空間  是指允許存在多個同名函式,而這些函式的引數表不同。
重定義/隱藏  不同名字空間 用於繼承,派生類與基類的函式同名,遮蔽基類的函式
重寫/覆蓋 不同名字空間
用於繼承,子類重新定義父類虛擬函式的方法

41、多型的作用?

【參考答案】
主要是兩個:
1. 隱藏實現細節,使得程式碼能夠模組化;擴充套件程式碼模組,實現程式碼重用;
2. 介面重用:為了類在繼承和派生的時候,保證使用家族中任一類的例項的某一屬性時的正確呼叫。

42、當一個類A 中沒有聲命任何成員變數與成員函式,這時sizeof(A)的值是多少,如果不是零,請解釋一下編譯器為什麼沒有讓它為零。

【標準答案】
sizeof(A) = 1;

43、如果 ClassA 中定義並實現虛擬函式 int func(void),ClassB 中也實現該函式,那麼上述變數 a->func() 將呼叫哪個類裡面的函式?如果 int func(void) 不是虛擬函式,情況又如何?為什麼?

【參考答案】
第一問呼叫的是B的。第二問呼叫A的。
虛擬函式的一個典型應用,虛擬函式只能藉助於指標或者引用來達到多型的效果。

44、 C++裡面是不是所有的動作都是main()引起的?如果不是,請舉例。

【參考答案】
比如全域性變數的初始化,就不是由 main 函式引起的。舉例:        

class   A{

};

A   a;   //a的建構函式限執行

int   main() {

}

複製程式碼

45、 行內函數在編譯時是否做引數型別檢查

【參考答案】
行內函數要做引數型別檢查,   這是行內函數跟巨集相比的優勢。                                                                 

46、請講一講解構函式和虛擬函式的用法和作用? 

【參考答案】
解構函式是特殊的類成員函式,它沒有返回型別,沒有引數,不能隨意呼叫,也沒有過載,只有在類物件的生命期結束的時候,由系統自動呼叫。
有適放記憶體空間的作用。
虛擬函式是C++多型的一種表現, 使用虛擬函式,我們可以靈活的進行動態繫結,當然是以一定的開銷為代價。

47、“new”in c++ is a?

A. library function like malloc in c 
B. key word
C. operator
D. none of the above
【參考答案】C。
malloc是庫函式,不在編譯器控制範圍之內;new是運算子,在編譯器控制範圍之內。   
呼叫malloc時,從堆中申請記憶體;呼叫new時,從堆中申請記憶體併為記憶體呼叫建構函式。

48、對於C++中類(class) 與結構(struct)的描述正確的為:

A、類中的成員預設是private的,但是可以宣告public,private 和 protected,結構中定義的成員預設的都是public;
B、結構中不允許定義成員函式,但是類中可以定義成員函式;
C、結構例項使用malloc() 動態建立,類物件使用new 操作符動態分配記憶體;
D、結構和類物件都必須使用new 建立;
E、結構中不可以定義虛擬函式,但是類中可以定義虛擬函式.
F、結構不可以存在繼承關係,但是類可以存在繼承關係.
【標準答案】A,D

49、兩個互相獨立的類:ClassA 和 ClassB,都各自定義了非靜態的公有成員函式 PublicFunc() 和非靜態的私有成員函式 PrivateFunc(); 現在要在ClassA 中增加定義一個成員函式ClassA::AdditionalPunction(ClassA a,ClassB b);則可以在AdditionalPunction(ClassA x,ClassB y)的實現部分(函式功能體內部)出現的合法的表達是最全的是:

A、x.PrivateFunc();x.PublicFunc();y.PrivateFunc();y.PublicFunc();
B、x.PrivateFunc();x.PublicFunc();y.PublicFunc();
C、x.PrivateFunc();y.PrivateFunc();y.PublicFunc();
D、x.PublicFunc();y.PublicFunc();
【標準答案】B

50、C++程式下列說法正確的有:

A、對呼叫的虛擬函式和模板類都進行遲後編譯.
B、基類與子類中函式如果要構成虛擬函式,除了要求在基  類中用virtual 聲名,而且必須名字相同且引數型別相同返回型別相同。
C、過載的類成員函式都必須要:或者返回型別不同,或者引數數目不同,或者引數序列的型別不同.
D、靜態成員函式和行內函數不能是虛擬函式,友員函式和建構函式也不能是虛擬函式,但是解構函式可以是虛擬函式.
【標準答案】A

51、在C++中有沒有純虛建構函式? 

【標準答案】建構函式不能是虛的。只能有虛的解構函式。

52、下面的 throw 表示式哪些是錯誤的?

(a) class exceptionType { }; 
     throw exceptionType { }; 
(b) enum mathErr { overflow, underflow, zeroDivide }; 
    throw zeroDivide(); 
【標準答案】
(a) class exceptionType { }; 
     throw exceptionType();
(b) enum mathErr { overflow, underflow, zeroDivide }; 
    throw zeroDivide; 

53、談談你是怎麼認識 C++ 中的模板的?

【參考答案】
模板使程式設計師能夠快速建立具有型別安全的類庫集合和函式集合,它的實現,方便了大規模的軟體開發。(結合stl更好)

54、在 C++的一個類中宣告一個 static 成員變數有沒有用?

【參考答案】
在C++類的成員變數被宣告為 static(稱為靜態成員變數),意味著它為該類的所有例項所共享,也就是說當某個類的例項修改了該靜態成員變數,
也就是說不管建立多少物件,static修飾的變數只佔有一塊記憶體。其修改值為該類的其它所有例項所見;而類的靜態成員函式也只能訪問靜態成員(變數或函式)。static是加了訪問控制的全域性變數,不被繼承。

55、C++中為什麼用模板類?

【參考答案】
(1)可用來建立動態增長和減小的資料結構
(2)它是型別無關的,因此具有很高的可複用性。
(3)它在編譯時而不是執行時檢查資料型別,保證了型別安全(4)它是平臺無關的,可移植性(5)可用於基本資料型別

56、函式模板與類模板有什麼區別?

【參考答案】
函式模板的例項化是由編譯程式在處理函式呼叫時自動完成的,而類模板的例項化必須由程式設計師在程式中顯式地指定。

58、請你談談你在類中如何使用 const 的。

【參考答案】
有時我們希望某些常量只在類中有效。由於#define 定義的巨集常量是全域性的,不能達到目的,於是想當然地覺得應該用 const 修飾資料成員來實現。
const 資料成員的確是存在的,但其含義卻不是我們所期望的。const 資料成員只在某個物件生存期內是常量,而對於整個類而言卻是可變的,因為類可以建立多個物件,不同的物件其 const 資料成員的值可以不同。 不能在類宣告中初始化 const 資料成員。

const 資料成員的初始化只能在類建構函式的初始化表中進行。

59、函式過載,我們靠什麼來區分呼叫的那個函式?靠返回值判斷可以不可以?

【參考答案】
如果同名函式的引數不同(包括型別、順序不同) ,那麼容易區別出它們是不同的。如果同名函式僅僅是返回值型別不同,有時可以區分,有時卻不能。例如: 
void Function(void); 
int  Function (void); 
上述兩個函式,第一個沒有返回值,第二個的返回值是 int 型別。如果這樣呼叫函式: 
int  x = Function (); 
則可以判斷出 Function 是第二個函式。問題是在 C++/C 程式中,我們可以忽略函式的返回值。在這種情況下,編譯器和程式設計師都不知道哪個 Function 函式被呼叫。 所以只能靠引數而不能靠返回值型別的不同來區分過載函式。

60、所有的運算子都能過載嗎?

【參考答案】
不能被過載的運算子 
在 C++運算子集合中,有一些運算子是不允許被過載的。這種限制是出於安全方面的考慮,可防止錯誤和混亂。 
(1)不能改變 C++內部資料型別(如 int,float 等)的運算子。 
(2)不能過載‘.’,因為‘.’在類中對任何成員都有意義,已經成為標準用法。 
(3)不能過載目前 C++運算子集合中沒有的符號,如#,@,$等。原因有兩點,一是難以理解,二是難以確定優先順序。 
(4)對已經存在的運算子進行過載時,不能改變優先順序規則,否則將引起混亂。 

61、基類的解構函式不是虛擬函式,會帶來什麼問題?

【參考答案】
派生類的解構函式用不上,會造成資源的洩漏。

第四部分:程式閱讀題(62-90)

62、main 函式執行以前,還會執行什麼程式碼?

【參考答案】
全域性物件的建構函式會在main 函式之前執行。


63、 There are two int variables: a and b, don't use“if”, “? :”, “switch”or other judgement statements, find out the biggest one of the two numbers.

【標準答案】
( ( a + b ) + abs( a - b ) ) / 2

64、如何打印出當前原始檔的檔名以及原始檔的當前行號?

【標準答案】
cout << __FILE__ ;
cout<<__LINE__ ;
__FILE__和__LINE__是系統預定義巨集,這種巨集並不是在某個檔案中定義的,而是由編譯器定義的。(C也有)

65、下面兩種if語句判斷方式。請問哪種寫法更好?為什麼?  

int n;
if (n == 10) // 第一種判斷方式
if (10 == n) // 第二種判斷方式
【參考答案】
這是一個風格問題,第二種方式如果少了個=號,編譯時就會報錯,減少了出錯的可能行,可以檢測出是否少了=。

66、寫出執行結果:

{

    // test1  char str[] = "world";

     cout << sizeof(str) << ": ";

    char *p = str;

    cout << sizeof(p) << ": ";

    char i = 10;

    cout << sizeof(i) << ": ";

    void *pp = malloc(10);

     cout << sizeof(pp) << endl;

}

複製程式碼
【標準答案】6:4:1:4

67、在不用第三方引數的情況下,交換兩個引數的值。

【參考答案】
a = a + b; 
b = a – b; a = a – b;

68、以下程式碼如果有錯,請該正,並寫出輸出結果? 

void main(void)

{

    int nArrLength(400), i = 546;     

    for (int i = 0; i< 99999999999; i++);

        cout << nArrLength << endl;

    cout << i << endl;

}

複製程式碼

【標準答案】

void main(void)

{         

        int nArrLength(400), i = 546;        

                 /*主要是考看對C++的基礎知識是否瞭解這裡的int nArrLength(400)是對整數的定義,當然,明名上有問題,這裡是故意這樣的,

                但是,最好是變數名改為 ....[還是您自己看著辦了]*/

         for (int i = 0; i< 99999999999; i++); 

                /*這裡是考對變數越界理解,同時....,所以,999...應該改為 ~((int)0),也就是整數中0取反考對變數塊作用域的理解,這裡的i,在迴圈後就不存在了*/           

        cout << nArrLength << endl;           // 這裡輸出 400          

        cout << i << endl;                    // 這裡輸出 546 

  }

複製程式碼

69、int i = 5, b = 7; cout << (i+++b) <<endl; 不用除錯,請說出,以上程式碼在gcc編譯過後的執行結果!

【標準答案】結果是12。

70、寫一個能做左值的函式(方法有很多)。

如:max(x, y) += 2874 + 55; drwline(x, y)++;
【參考答案】  

int &max(int & x, int & y)

{

    return x > y? x : y;

}

int x = 55, y = 77;

max(x, y) += 12 + 11; // 此時 y = 92;

cout << "x = "x << "; y = "<< y << endl; // 輸出 x = 55; y = 92;

複製程式碼

71、程式輸出

class human

{

public:

        ~human()

        {

                cout << "human over......" << endl;

        }

        void Disp()

        {

                cout << "human disp ... ..." << endl;

        }

};

class man : public human

{

public:

        ~man()

        {

                cout << "man over......" << endl;

        }

        void Disp()

        {

                cout << "man disp ... ..." << endl;

        }

};

int main()

{

        human* p = new human;

        p->Disp();

        delete p;

        return 0;

}

複製程式碼

【標準答案】 
human disp ... ... 
human over ......

72、下面的函式實現在一個固定的數上加上一個數,有什麼錯誤,改正:

int add_n(int n)

{    

    static int i = 100;

     i += n;

    return i;

}

複製程式碼

【標準答案】 
因為static使得i的值會保留上次的值。以後的i會一直更新,使得第二次調用出現錯誤, 去掉static就可了

73、寫出列印結果
unsigned short array[]={1,2,3,4,5,6,7};
int i = 3;   
*(array + i) =  ?

【標準答案】4

74、寫一個函式計算當引數為n(n很大)時的值 1-2+3-4+5-6+7......+n。

【參考答案】

long fn(long n)

{     

if(n <= 0)

{          

    printf("error: n must > 0);        

    exit(1);      

}

if(0 == n % 2)        

    return (n / 2) * (-1);    

else          

    return (n / 2) * (-1) + n;

複製程式碼

75、字元指標、浮點數指標、以及函式指標這三種類型的變數哪個佔用的記憶體最大?為什麼?

【參考答案】
指標變數也佔用記憶體單元,而且所有指標變數佔用記憶體單元的數量都是相同的。
就是說,不管是指向何種物件的指標變數,它們佔用記憶體的位元組數都是一樣的,並且要足夠把程式中所能用到的最大地址表示出來(通常是一個機器字長)。

76、以下三條輸出語句分別輸出什麼?

char str1[]       = "abc";  

char str2[]       = "abc";  

const char str3[] = "abc";   

const char str4[] = "abc";   

const char* str5  = "abc";  

const char* str6  = "abc";  

cout << boolalpha << ( str1==str2 ) << endl; // 輸出什麼?  

cout << boolalpha << ( str3==str4 ) << endl; // 輸出什麼?  

cout << boolalpha << ( str5==str6 ) << endl; // 輸出什麼?  

複製程式碼

【參考答案】
分別輸出 false,false,true。
str1和str2都是字元陣列,每個都有其自己的儲存區,它們的值則是各儲存區首地址,不等;
str3和str4同上,只是按const語義,它們所指向的資料區不能修改。
str5和str6並非陣列而是字元指標,並不分配儲存區,其後的“abc”以常量形式存於靜態資料區,而它們自己僅是指向該區首地址的指標,相等。

77、以下程式碼有什麼問題?     

cout << (true?1:"1") << endl;

複製程式碼
【參考答案】
三元表示式“?:”問號後面的兩個運算元必須為同一型別。

78、以下程式碼能夠編譯通過嗎,為什麼?

unsigned int const size1 = 2;  

char str1[ size1 ];  

unsigned int temp = 0;  

cin >> temp;  

unsigned int const size2 = temp;  

char str2[ size2 ];

複製程式碼

【標準答案】
str2定義出錯,size2非編譯器期間常量,而陣列定義要求長度必須為編譯期常量。

79、以下程式碼中的輸出語句輸出0嗎,為什麼?

struct CLS  

{  

      int m_i;  

      CLS( int i ) : m_i(i) {}  

      CLS()  

      {  

          CLS(0);  

      }  

};  

CLS obj;  

cout << obj.m_i << endl;

複製程式碼

【標準答案】
不能。在預設建構函式內部再呼叫帶參的建構函式屬使用者行為而非編譯器行為,亦即僅執行函式呼叫,而不會執行其後的初始化表示式。
只有在生成物件時,初始化表示式才會隨相應的建構函式一起呼叫。

80、How do you code an infinite loop in Cplus plus ?

【參考答案】
while(1){} or for(;1;)

81、What are the values of a, b, and c after the following instructions: 

int a=5, b=7, c;

c = a+++b;

複製程式碼

【標準答案】a=6,b=7,c=12

82、在排序方法中,關鍵碼比較次數與記錄地初始排列無關的是()

A. Shell排序      
B. 歸併排序
C. 直接插入排序     
D. 選擇排序 
【標準答案】D

83、程式碼:
void func()  {    
    static int val;
}
中,變數 val 的記憶體地址位於: 
A. 已初始化資料段
B.未初始化資料段     
C.堆
D.棧 
【標準答案】A

84、一個棧的入棧序列是 A,B,C,D,E,則棧的不可能的輸出序列是?

A、EDCBA;
B、DECBA;    
C、DCEAB;
D、ABCDE 
【標準答案】C

85、寫出判斷ABCD四個表示式的是否正確, 若正確, 寫出經過表示式中 a 的值。

int a = 4;  

(A)、a += (a++);

(B)、a += (++a) ;  

(C)、(a++) += a;

(D)、(++a) += (a++);  

a = ?

複製程式碼

【參考答案】
C錯誤,左側不是一個有效變數,不能賦值,可改為 (++a) += a; 改後答案依次為 9,10,10,11

86、請你談談你是如何使用 return 語句的。

【參考答案】
(1)return 語句不可返回指向“棧記憶體”的“指標”或者“引用” ,因為該記憶體在函式體結束時被自動銷燬。
(2)要搞清楚返回的究竟是“值”、“指標”還是“引用” 。
(3)如果函式返回值是一個物件,要考慮 return 語句的效率。


87、① return String(s1 + s2); 和 ②String temp(s1 + s2); return temp; 一樣嗎?

【參考答案】 
①這是臨時物件的語法,表示“建立一個臨時物件並返回它” 。
②將發生三件事。首先,temp 物件被建立,同時完成初始化;然後拷貝建構函式把 temp 拷貝到儲存返回值的外部儲存單元中;
最後,temp 在函式結束時被銷燬(呼叫解構函式) 。然而“建立一個臨時物件並返回它”的過程是不同的,
編譯器直接把臨時物件建立並初始化在外部儲存單元中,省去了拷貝和析構的化費,提高了效率。

88、下列程式的執行結果是?

#include <iostream>    

const char *str = "vermeer";    

int main()   

{   

    const char *pstr = str;   

    cout << "The address of pstr is: " << pstr << endl;   

}

複製程式碼

【標準答案】
The address of pstr is: vermeer

89、下列程式輸出結果是?

inline void max_out( int val1, int val2 )

{  

    cout << ( val1 > val2 ) ? val1 : val2;

}

int main()

{

    int ix = 10, jx = 20;

    cout << "The larger of " << ix;

    cout << ", " << jx << " is ";

    max_out( ix, jx );

    cout << endl;

}

複製程式碼

【標準答案】
The larger of 10, 20 is 0 ,
為什麼不是20呢?問題在於輸出操作符的優先順序高於條件操作符 所以輸出 val1 和 val2 比較結果的 true/false

90、int max( int *ia, int sz ); 
int max( int *, int = 10 ); 
算函式過載?還是重複宣告?

【標準答案】
如果在兩個函式的引數表中只有預設實參不同則第二個宣告被視為第一個的重複宣告 。

第六部分:程式設計練習(比C要難)(91-100)

91、請編寫一個 C++函式,該函式給出一個位元組中被置 1 的位的個數。

【參考答案】

unsigned int TestAsOne0(char log)

{

        int i;

        unsigned int num = 0, val;

        for (i = 0; i < 8; i++)

        {

                val = log >> i;     //移位                    

                val &= 0x01;     //與1相與                    

                if (val)

                        num++;

        }

        return num;

}

複製程式碼

92、編寫一個函式,函式接收一個字串,是由十六進位制陣列成的一組字串,函式的功能是把接到的這組字串轉換成十進位制數字.並將十進位制數字返回。

【參考答案】

BOOL HexToDec(LPCTSTR shex, int& idec)

{

        int i, mid;

        int len = lstrlen(shex);

        if (len > 8)

                return FALSE;

        mid = 0;

        idec = 0;

        for (i = 0; i < len; i++)

        {

                if (shex[i] >= '0'&&shex[i] <= '9')

                        mid = shex[i] - '0';

                else   if (shex[i] >= 'a'&&shex[i] <= 'f')

                        mid = shex[i] - 'a' + 10;

                else   if (shex[i] >= 'A'&&shex[i] <= 'F')

                        mid = shex[i] - 'A' + 10;

                else

                        return   FALSE;

                mid <<= ((len - i - 1) << 2);   // 移位表示變為2的n次方倍  

                idec = idc + mid;

        }

        return TRUE;

}

複製程式碼

93、輸入一個字串,將其逆序後輸出 。

【參考答案】

void main()

{

        char a[50];

        memset(a, 0, sizeof(a));

        int i = 0, j;

        char t;

        cin.getline(a, 50, '\n');

        for (i = 0, j = strlen(a) - 1; i < strlen(a) / 2; i++, j--)

        {

                t = a[i];

                a[i] = a[j];

                a[j] = t;

        }

        cout << a << endl;

}

複製程式碼

94、編寫一個演算法frequency,統計在一個輸入字串中各個不同字元出現的頻度。用適當的測試資料來驗證這個演算法。

【參考答案】

void frequency(String& s, char& A[], int& C[], int &k)

{

        int i, j, len = s.length();

        if (!len) { cout << "The string is empty. " << endl;  k = 0;  return; }

        else

        {

                A[0] = s[0];  C[0] = 1;  k = 1;     /*語句s[i]是串的過載操作*/

                for (i = 1; i < len; i++) C[i] = 0;            /*初始化*/

                for (i = 1; i < len; i++)

                {           /*檢測串中所有字元*/

                        j = 0;   while (j < k && A[j] != s[i]) j++; /*檢查s[i]是否已在A[ ]中*/

                        if (j == k)

                        {

                                A[k] = s[i]; C[k]++; k++

                        }        /*s[i]從未檢測過*/

                        else C[j]++;            /*s[i]已經檢測過*/

                }

        }

}

複製程式碼

95、假設以陣列Q[m]存放迴圈佇列中的元素, 同時以rear和length分別指示環形佇列中的隊尾位置和佇列中所含元素的個數。試給出該迴圈佇列的隊空條件和隊滿條件, 並寫出相應的插入(enqueue)和刪除(dlqueue)元素的操作。

【參考答案】迴圈佇列類定義

#include <assert.h>  

template <class Type> class Queue {   //迴圈佇列的類定義  

public:   

    Queue ( int=10 );  

    ~Queue ( ) { delete [ ] elements; }  

    void EnQueue ( Type & item );  

    Type DeQueue ( );  

    Type GetFront ( );  

    void MakeEmpty ( ) { length = 0; }      //置空佇列  

    int IsEmpty ( ) const { return length == 0; }   //判佇列空否  

    int IsFull ( ) const { return length == maxSize; }  //判佇列滿否  

private:      

    int rear, length;               //隊尾指標和佇列長度  

    Type *elements;             //存放佇列元素的陣列  

    int maxSize;                //佇列最大可容納元素個數  

};

複製程式碼

template <class Type>

Queue<Type>::Queue(int sz) : rear(maxSize - 1), length(0), maxSize(sz)

{

        //建立一個最大具有maxSize個元素的空佇列。

        elements = new Type[maxSize];//建立佇列空間

        assert(elements != 0);//斷言: 動態儲存分配成功與否

}

template<class Type>

void Queue<Type>::EnQueue(Type &item)

{

        assert(!IsFull());//判佇列是否不滿,滿則出錯處理

        length++;//長度加1

        rear = (rear + 1) % maxSize;//隊尾位置進1

        elements[rear] = item;//進佇列

}

template<class Type>

Type Queue<Type> ::DeQueue()

{

        assert(!IsEmpty());//判斷佇列是否不空,空則出錯處理

        length--;//佇列長度減1

        return elements[(rear - length + maxSize) % maxSize];//返回原隊頭元素值

}

template<class Type>

Type Queue<Type> ::GetFront()

{

        assert(!IsEmpty());

        return elements[(rear - length + 1 + maxSize) % maxSize];//返回隊頭元素值

}

複製程式碼

96、已知A[n]為整數陣列,試寫出實現下列運算的遞迴演算法:

(1) 求陣列A中的最大整數。
(2) 求n個整數的和。
(3) 求n個整數的平均值。

【參考答案】

#include <iostream.h>   

class RecurveArray   

{                   //陣列類宣告   

private:    int *Elements;      //陣列指標    

        int ArraySize;      //陣列尺寸  

        int CurrentSize;        //當前已有陣列元素個數   

public :  

        RecurveArray ( int MaxSize =10 ) :  

        ArraySize ( MaxSize ), Elements ( new int[MaxSize] ){ }   

        ~RecurveArray ( ) { delete [ ] Elements; }   

        void InputArray();      //輸入陣列的內容   

        int MaxKey ( int n );       //求最大值   

        int Sum ( int n );      //求陣列元素之和  

        float Average ( int n );    //求陣列元素的平均值  

};  

void RecurveArray :: InputArray ( )  

{                   //輸入陣列的內容  

        cout << "Input the number of Array: \n";  

        for ( int i = 0; i < ArraySize; i++ ) cin >> Elements[i];  

}  

int RecurveArray :: MaxKey ( int n )   

{           //遞迴求最大值  

        if ( n == 1 ) return Elements[0];  

        int temp = MaxKey ( n - 1 );  

        if ( Elements[n-1] > temp ) return Elements[n-1];  

        el