1. C++ 中類與結構體的區別
答:類成員預設存取權限為私人(private),結構體成員預設存取權限為公用(public),其他地方完全一樣。
---------------------------------------------------------------------------
2. 關於私人繼承
私人繼承實際上和組合比較相像,應該說是一個設計概念,而不是具體的實現概念。具體實現中私人繼承使用比較少,因為大多數情況使用組合更加清晰。
公有繼承意味著 is-a,私人繼承意味著 is-implemented-in-terms-of (根據...實現)。
參考:《C++箴言:謹慎使用私人繼承》
http://tech.163.com/05/1124/14/23B2S17F0009159Q.html
---------------------------------------------------------------------------
3. 寫出下面程式的輸出。
#include <stdio.h>
class abc;
void del(abc *pobj)
{
delete pobj;
}
class abc
{
public:
abc(){
printf("abc/r/n");
}
~abc(){
printf("~abc/r/n");
}
};
int main(int argc, char *argv[])
{
abc *pobj = new abc;
del(pobj);
}
答:
abc
說明:定義 del 函數的時候,abc 的解構函式未定義,因此不會調用。
---------------------------------------------------------------------------
4. 寫出下面程式的輸出。
#include <stdio.h>
#include <stdlib.h>
void * operator new(size_t size)
{
printf("malloc %u/r/n", size);
return malloc(size);
}
void operator delete(void * memblock)
{
printf("free/r/n");
return free(memblock);
}
class abc
{
public:
abc()
{
printf("abc/r/n");
throw int();
}
~abc()
{
printf("~abc/r/n");
}
};
int main(int argc, char * argv[])
{
try
{
new abc;
}
catch (int & i)
{
printf("%d/r/n", i);
}
return 0;
}
答:
malloc 1
abc
free
0
如果將“new abc;”換成“abc a;”,結果將是:
abc
0
說明:
1. 在 C++ 中,建構函式拋出異常後不會觸發解構函式的調用,這和 object pascal 不一樣。C++ 認為構造失敗意味著對象沒有產生,既然沒有生就沒有死。然而,當建構函式拋出異常時,仍會調用 delete 函數以釋放記憶體。
operator new 重載全域 new,所以下面構造的時候 new 肯定會調用該 operator new。operator delete 同樣。因此先輸出 malloc 1。
new 分配完記憶體後,會自動調用建構函式,所以輸出 abc。
在建構函式內部,拋出異常,throw int();
這個異常被捕獲,輸出 i,其值為 0。
但是在捕獲的異常被處理之前,必須先釋放記憶體。因為異常出錯,但此時 new 分配記憶體的工作已經完成,如果不進行 delete 的話,勢必會記憶體泄露。
2. 當產生堆棧對象時,C++ 自動調用的 operator new 和 operator delete 是全域的 operator new 和 operator delete。
參考:
《More Effective C++》條款10: 在建構函式中防止資源泄漏
…… 不用為 BookEntry 中的非指標資料成員操心,在類的建構函式被調用之前資料成員就被自動地初始化。所以如果
BookEntry 建構函式體開始執行,對象的 theName、theAddress 和 thePhones
資料成員已經被完全構造好了。這些資料可以被看做是完全構造的對象,所以它們將被自動釋放,不用你介入操作。……
---------------------------------------------------------------------------
5. 寫出下面程式的輸出。
#include <stdio.h>
template <typename T>
class abc{
public:
abc(){
printf("primary/r/n");
}
};
template<>
abc<int>::abc()
{
printf("member spec/r/n");
};
template<typename T, typename P>
class abc<T (*)(P)>
{
public:
abc(){
printf("partial spec/r/n");
}
};
int main(int argc, char *argv[])
{
abc<void* (*)(int)> f_abc;
abc<int> i_abc;
}
答:
partial spec
member spec
說明:模板部分特化。
---------------------------------------------------------------------------
6. 下面的代碼能否通過編譯?為什嗎?
class a
{
public:
virtual ~a()
{
}
private:
void operator delete(void *p);
};
int main(int argc, char *argv[])
{
a _1;
}
答:
不能
說明:
1) 如果一個類有虛解構函式的話,那麼自訂 delete 函數必須有函數體。
2) 這個題目中,並不會調用 delete 函數。
3) 對於本題,delete 函數不被調用,但是編譯器需要它,因此,不能沒有定義。
參考:
如果對象是動態建立(也就是 new 出來的),那麼在 delete 的時候系統會先調解構函式然後調 operator
delete。編譯器在編譯的時候會把這 2 個步驟合并到一個函數裡,看反組譯碼就知道了,函數名字類似 'scalar deleting
destructor'。如果只是聲明了 operator delete 函數而沒有定義,那麼編譯的時候會得不到函數地址,這樣產生
'scalar deleting destructor' 內建函數的時候就會報錯了。
---------------------------------------------------------------------------
7. C 與 C++ 中 static 函數有什麼區別?
C 語言中 static 關鍵字作用於函數時起限制函數範圍的作用,其 static 函數範圍被限制為當前檔案中,該函數定義之後部分。
C++ 的全域函數用 static 修飾和 C 語言中一個意思 (C++ 標準建議此種情況用匿名名字空間包含該函數來代替 static 關鍵字);但類成員函數如果用 static 修飾表示是類的範圍而不是對象範圍,可以直接通過類名來引用。
---------------------------------------------------------------------------
8. const 函數的作用。
類的設計者通過將函式宣告為 const 以表明它們不修改類對象。
const 函數內不允許修改資料成員 (需要注意的是,雖然在 const 函數內,指標成員變數不允許被修改,但對指標所指向內容的修改是允許的)。
一個 const 類對象只能調用 const 成員函數 (構造和解構函式除外)。
---------------------------------------------------------------------------
9. 拷貝建構函式什麼情況下會用到?實現時有什麼注意點?
拷貝建構函式的幾個用處:
1) 用一個類對象初始化該類的另一個對象的時候:
A a;
A b(a);
A b = a;
2) 把一個類對象賦值給該類的另一個對象的時候:
A b;
b = a;
3) 傳參數和返回時:
A f (A a) // 傳參和返回都會調用拷貝建構函式
{
// ...
}
實現時要注意的是:
1) 當類中有指標變數成員時,確認是直接拷貝指標變數的值,還是重新分配記憶體然後遞迴拷貝構造。
2) 是否有每個對象必須有唯一值的成員變數 (比如帳號)。其實 1) 也可以歸為 2)。
---------------------------------------------------------------------------
10. 寫出函數指標,返回指標的函數,const 指標,指向 const 的指標,指向 const 的 const 指標。
void (* f)()
void * f()
int * const f
const int * f
const int * const f
---------------------------------------------------------------------------
11. 智能指標。
智能指標就是類比指標動作的類。所有的智能指標都會重載 -> 和 * 操作符。
智能指標還有許多其他功能,比較有用的是自動銷毀。這主要是利用棧對象的有限範圍以及臨時對象(有限範圍實現)解構函式釋放記憶體。當然,智能指標還不
止這些,還包括複製時可以修改來源物件等。智能指標根據需求不同,設計也不同(寫時複製,賦值即釋放對象擁有許可權,引用計數等,控制權轉移等)。這個主題可
以講一本書。
auto_ptr 即是一種常見的智能指標。
智能指標通常用類模板實現:
template <class T>
class smpoint
{
public:
smpoint(T * p): _p(p){}
T & operator * (){return *_p;}
T * operator -> (){return _p;}
~smpoint(){delete _p;}
private:
T * _p;
}
---------------------------------------------------------------------------
12. 標準模板庫 vector 追加資料如何??注意是底層如何?,而不是如何使用。
關鍵點是,在追加對象前先判斷預留的空間是否滿足需求,如果不滿足則根據分配策略,另分配足夠的空間
(一般使用平方增加策略),複製以前的對象數組,再釋放原來的空間,然後把對象追加到尾部。如果任何一個操作環節失敗,則至少保留原數組不受影響(異常安
全保證策略)。