Posted on 2010-04-25 15:00
~William~ 閱讀(1567)
評論(0) 編輯 收藏 引用 所屬分類:
c++基礎(chǔ)
C++ 面試題
1.類成員指針
Class test
{
Public:
Int
fun(int) const;
Int
fun(int);
Static
int fun(int);
Int
iTemp;
}
1.1 非靜態(tài)成員函數(shù)指針
定義:
int (Test::*pFun)(int) = &Test::fun;
int (Test::*pFunConst)(int)const = &Test::fun;
使用:
Test a;
const Test b;
(a.*pFun)(2) 或 (a.*pFunConst)(2);
(b.*pFunConst)(2);
不能用(b.*pFun)(2);
1.2 非靜態(tài)成員變量
int Test::*pInt = &Test::iTemp;
(a.*pInt) = 3;
1.3 靜態(tài)成員函數(shù)指針
int (*pFun)() = &Test::fun;
或 int (*pFun)() = Test::fun; 都正確;(注:定義無域操作符)
使用:
(*pFun)() 或 pFun() 都正確;
2.非成員函數(shù)指針和靜態(tài)成員函數(shù)一致。
3.非成員函數(shù)和靜態(tài)成員函數(shù)上不允許修飾符。例如 void fun() const; void fun()
volatile;
但非靜態(tài) 成員函數(shù)允許const、volatile等修飾符。
4.變量修飾符
auto:指定數(shù)據(jù)存儲在棧中。局部變量默認(rèn)為auto。該修飾符不能用于成員變量和全局變量。
static:
局部變量表示存儲在靜態(tài)空間,全局變量表示不允許外部引用。
volatile:表示該變量可能隨時改變,不要做任何假設(shè)優(yōu)化。
mutale:
去除成員變量的const屬性。
extern:全局變量默認(rèn)為extern屬性,表示可被外部引用,此時與static相對。
extern int a =2; 表示定義一個可被外部引用的變量。
extern int a; 表示引用外部變量。
5.數(shù)據(jù)類型隱式轉(zhuǎn)換
短數(shù)據(jù)->長數(shù)據(jù) (eg: float -> double)
有符號->無符號 (eg: int -> unsigned int )PS: 所以
int(-1)>unsigned int(1);
低精度->高精度 (eg: int -> float)
6.memcpy 有“防重疊”覆蓋機(jī)制,strcpy 沒有。
7.float表示
共計(jì)32位,折合4字節(jié)
由最高到最低位分別是第31、30、29、……、0位
31位是 符號位,1表示該數(shù)為負(fù),0反之。
30-23位,一共8位是指數(shù)位。
22-0位,一共23位是尾數(shù)位。
每 8位分為一組,分成4組,分別是A組、B組、C組、D組。
每一組是一個字節(jié),在內(nèi)存中逆序存儲,即:DCBA
8.不能在類的聲明中初始化類常量,而只能在構(gòu)造函數(shù)初始化列表來初始化
9.類中的枚舉常量不占用對象的存儲空間
10.有時候函數(shù)原本不需要返回值,但為了增加靈活性如支持鏈?zhǔn)奖磉_(dá),可以附加返回值。
11.賦值函數(shù),應(yīng)當(dāng)用“引用傳遞”的方式返回String 對象。如果用“值傳遞”的方式,雖然功能仍然正確,但由于return 語句要把 *this 拷貝到保存返回值的外部存儲單元之中,增加了不必要的開銷,降低了賦值函數(shù)的效率。
12.對于非內(nèi)部數(shù)據(jù)類型的對象而言,光用maloc/free 無法滿足動態(tài)對象的要求。對象在創(chuàng)建的同時要自動執(zhí)行構(gòu)造函數(shù), 對象在消亡之前要自動執(zhí)行析構(gòu)函數(shù)。如果用free 釋放“new 創(chuàng)建的動態(tài)對象”,那么該對象因無法執(zhí)行析構(gòu)函數(shù)而可能導(dǎo)致程序出錯。如果用delete 釋放“malloc 申請的動態(tài)內(nèi)存”,理論上講程序不會出錯,但是該程序的可讀性很差。
13.如果用new 創(chuàng)建對象數(shù)組,那么只能使用對象的無參數(shù)構(gòu)造函數(shù),delete時如果對象沒有析構(gòu)函數(shù),則delete和delete[]是功能相同的。
14.只能靠參數(shù)而不能靠返回值類型的不同來區(qū)分重載函數(shù)。編譯器根據(jù)參數(shù)為每個重載函數(shù)產(chǎn)生不同的內(nèi)部標(biāo)識符。并不是兩個函數(shù)的名字相同就能構(gòu)成重載。全局函 數(shù)和類的成員函數(shù)同名不算重載,因?yàn)楹瘮?shù)的作用域不同。
15.關(guān)鍵字inline
必須與函數(shù)定義體放在一起才能使函數(shù)成為內(nèi)聯(lián),僅將inline 放在函數(shù)聲明前面不起任何作用。定義在類聲明之中的成員函數(shù)將自動地成為內(nèi)聯(lián)函數(shù)。
以下情況不宜使用內(nèi)聯(lián):
(1)如果函數(shù)體內(nèi)的代碼比較長,使用內(nèi)聯(lián)將導(dǎo)致內(nèi)存消耗代價較高。
(2)如果函數(shù)體
內(nèi)出現(xiàn)循環(huán),那么執(zhí)行函數(shù)體內(nèi)代碼的時間要比函數(shù)調(diào)用的開銷大。
16.只有靜態(tài)常量整型數(shù)據(jù)成員才可以在類中初始化,普通成員只能在初始化列表或函數(shù)內(nèi)初始化,常量成員只能在初始化列表。成員對象初始化的次序完全不受它們在 初始化表中次序的影響,只由成員對象在類中聲明的次序決定。
17.拷貝構(gòu)造函數(shù)和賦值函數(shù)非常容易混淆,常導(dǎo)致錯寫、錯用。拷貝構(gòu)造函數(shù)是在對象被創(chuàng)建時調(diào)用的,而賦值函數(shù)只能被已經(jīng)存在了的對象調(diào)用。
18.不想編寫拷貝構(gòu)造函數(shù)和賦值函數(shù),又不允許別人使用編譯器生成的,則只需將拷貝構(gòu)造函數(shù)和賦值函數(shù)聲明為私有函數(shù),不用編寫代碼。
19.“const T”和“T const”總是都被允許的,而且是等效的。
注意在常量指針(const pointer)中,“const”永遠(yuǎn)出現(xiàn)在“*”之后。
例如:
int *const p1 = q; //指向int 變量的常量指針
int const* p2 = q; //指向int 常量的指針
const int* p3 = q; //指向int 常量的指針
20.一個常見的微妙問題是,一個函數(shù)風(fēng)格的宏并不遵守函數(shù)參數(shù)傳遞的規(guī)則。
21.沒有引用數(shù)組,但可有指向數(shù)組的引用,并且保留數(shù)組的邊界。
22.左值擁有保存值的位置,而右值則沒有相關(guān)地址,只是簡單值。
23.負(fù)索引是可以的,如p[-2]或(-2)[p]都是可以的(p必然不能是數(shù)組名),但必須保持不越界。
sum=p()+q()+r();不能保證p(),q(),r()調(diào)用的順序。
逗號運(yùn)算符","可以保證求值順序.result= ( p(),q(),r() );是先求p(),q(),然后將r()賦給result
24.在if的條件里聲明變量,且可在真假分支里面使用。
const int *
const * p;p是個指針,指向常指針的,常指針指向一個常量int。
25.不能用空白初始化列表來規(guī)定默認(rèn)的對象初始化.
class a;
a A(); //會警告,看起來像函數(shù)聲明
a *p=new a(); //ok
a *p=new a; //ok
26.可以寫一句只有數(shù)字的代碼,如1234;(void)0;可以編譯執(zhí)行,相當(dāng)于nop。
27.給函數(shù)指針賦值時可以對函數(shù)名取地址也可以不取,通過函數(shù)指針調(diào)用函數(shù)時可以用*也可不用。
28.static_cast可以轉(zhuǎn)換基本數(shù)據(jù)類型(int->char)、void*和有類型指針、基類和派生類指針的轉(zhuǎn)換(多重繼承也行,它可重新計(jì)算偏移地址),但是不能轉(zhuǎn)換如(int*->char*等)。
29.dynamic_cast主要用于執(zhí)行"安全的向下轉(zhuǎn)型",reinterpret_cast可執(zhí)行任何轉(zhuǎn)換,const_cast執(zhí)行去 const轉(zhuǎn)換。
30.將取地址運(yùn)算符用到完全限定的類成員名(包括變量和函數(shù)),就能獲得指向成員的地址。使用形式為"X::*"來聲明一個指向類X成員的指針。注意聲明成員 函數(shù)指針的時候不能像普通函數(shù)指針可以省略&或*的使用,但靜態(tài)成員函數(shù)則除外,它和普通函數(shù)一致。成員指針和普通指針不一樣,并非指向一個內(nèi)存 區(qū)域,而是相當(dāng)于一個結(jié)構(gòu)的偏移量,當(dāng)它和具體的對象結(jié)合就能指向特定對象的特定成員。
31.當(dāng)把派生類對象賦給基類對象的時候會產(chǎn)生切割現(xiàn)象,即針對派生類的數(shù)據(jù)和行為將產(chǎn)生切割。
32.多維數(shù)組的第1個元素是數(shù)組而非普通類型。
33.在含有單參數(shù)構(gòu)造函數(shù)的類中注意隱式轉(zhuǎn)換。如String
s="Hello";
34.函數(shù)對象是重載函數(shù)調(diào)用運(yùn)算符的類對象。
35.引用需要用左值進(jìn)行初始化,但指向常量的引用除外,編譯器將創(chuàng)建一個臨時左值。如const int c=12;//ok 一般情況下編譯器產(chǎn)生的臨時對象的生命期在它所在的最大表達(dá)式范圍內(nèi),但用臨時對象初始化常量對象的引用時會讓編譯器保證臨時對象和引用生命周期一樣。
36.可以將基類的成員指針(變量或函數(shù))安全的轉(zhuǎn)換為指向派生類成員的指針,但反之則不安全。
37.函數(shù)參數(shù)的傳遞是采用拷貝構(gòu)造函數(shù)而非賦值操作。對未初始化的對象賦值可能會出現(xiàn)意外,如類中含有未初始化指針。
38.聲明但不定義私有的拷貝構(gòu)造和賦值運(yùn)算將會關(guān)閉類的復(fù)制操作。并且賦值運(yùn)算、拷貝構(gòu)造函數(shù)和析構(gòu)函數(shù)不會被繼承,對派生類重載賦值運(yùn)算時需要調(diào)用基類的賦 值運(yùn)算。
39.在構(gòu)造函數(shù)里對成員變量初始化,比較好的方式是使用初始化列表。在初始化列表中靜態(tài)成員和數(shù)組不能被初始化。
類的初始化順序是虛擬基類的成員->非虛基類成員->類自身成員,和初始化列表的順序無關(guān)。
含有虛擬基類和不含的類在成員布局上不一樣,含有虛擬基類的類將虛擬基類的數(shù)據(jù)放在最后面。另外如B:virtual A,C:virtual
A,D:B,C;(均是虛繼承)則D的構(gòu)造函數(shù)將對A初始化一次(即使在初始化列表沒有顯式初始化A),B,C將不再對A初始化。
所有靜態(tài)數(shù)據(jù)(全局變量和靜態(tài)存儲變量)在使用前如未初始化其值都為0.全局變量可以存儲在靜態(tài)初始化區(qū)和未初始化區(qū)。
40.RVO返回值優(yōu)化,是指在函數(shù)返回中執(zhí)行拷貝初始化到直接初始化(使用帶非對象參數(shù)的構(gòu)造函數(shù))的轉(zhuǎn)換,NRV和RVO類似,但使用命名局部變量來保存返 回值。p160
41.重載、覆蓋和隱藏的區(qū)別
重載的特征:在同一個類,函數(shù)名相同,參數(shù)不同,virtual可有可無。
覆蓋的特征:在兩個類(基類和派生類),函數(shù)名和參數(shù)都相同,
且必須有virtual關(guān)鍵字。
隱藏的特征:基類函數(shù)名和派生類函數(shù)名相同參數(shù)不同,且不管是否有關(guān)鍵字。或函數(shù)名、參數(shù)均相同,但基類
函數(shù)沒有virtual(有的話就是覆蓋)。
不能覆蓋而只能隱藏基類非虛函數(shù)。
42.相同類型的所有對象公用一個虛函數(shù)表,在單繼承下不管有多少個虛函數(shù)都只有一個虛函數(shù)表指針。覆蓋就是在為派生類構(gòu)造虛函數(shù)表時用派生類的函數(shù)地址替換基 類成員函數(shù)地址的過程。
43.使用常量類成員可能在對類對象賦值的時候產(chǎn)生問題。
44.有時候我們可能會看到 if (NULL == p) 這樣古怪的格式。不是程序?qū)戝e了,是程序員為了防止將 if (p == NULL) 誤寫成 if (p = NULL),而有意把p 和NULL 顛倒。