標籤:
題(1)
運行中代碼,輸出的結果是什嗎?這段代碼有什麼問題?
<!-- lang: cpp -->#include <iostream>class A{ public: A() { std::cout << "A is created." << std::endl; } ~A() { std::cout << "A is deleted." << std::endl; }};class B : public A{ public: B() { std::cout << "B is created." << std::endl; } ~B() { std::cout << "B is deleted." << std::endl; }}; int _tmain(int argc, _TCHAR* argv[]){ A* pA = new B(); delete pA; return 0;}
答案:輸出三行,分別是:A is created. B is created. A is deleted。
用new建立B時,回調用B的建構函式。在調用B的建構函式的時候,會先調用A的建構函式。因此先輸出A is created. B is created.
接下來運行delete語句時,會調用解構函式。由於pA被聲明成類型A的指標,同時基類A的解構函式沒有標上virtual,因此只有A的解構函式被調用到,而不會調用B的解構函式。
由於pA實際上是指向一個B的執行個體的指標,但在析構的時候只調用了基類A的解構函式,卻沒有調用B的解構函式。這就會存在一個問題。如果在類型B中建立了一些資源,比如檔案控制代碼、記憶體等,在這種情況下都得不到釋放,從而導致資源泄漏。
建議定義解構函式為虛函數,這樣可以避免使用不當導致資源不能釋放。
PS:在建構函式中,虛函數會失去其動態綁定特性。
題(2)
我們可以用static修飾一個類的成員函數,也可以用const修飾類的成員函數(寫在函數的最後表示不能修改成員變數,不是指寫在前面表示傳回值為常量)。請問:能不能同時用static和const修飾類的成員函數?
答案:不可以。
C++編譯器在實現const的成員函數的時候為了確保該函數不能修改類的執行個體的狀態,會在函數中添加一個隱式的參數const this*。但當一個成員為static的時候,該函數是沒有this指標的。也就是說此時static的用法和static是衝突的。
我們也可以這樣理解:兩者的語意是矛盾的。static的作用是表示該函數只作用在類型的靜態變數上,與類的執行個體沒有關係;而const的作用是確保函數不能修改類的執行個體的狀態,與類型的靜態變數沒有關係。因此不能同時用它們。
題(3)
運行中的C++代碼,輸出是什嗎?
<!-- lang: cpp -->#include <iostream>class A{private: int n1; int n2;public: A(): n2(0), n1(n2 + 2) { } void Print() { std::cout << "n1: " << n1 << ", n2: " << n2 << std::endl; }};int _tmain(int argc, _TCHAR* argv[]){ A a; a.Print(); return 0;}
答案:輸出n1是一個隨機的數字,n2為0。
在C++中,成員變數的初始化順序與變數在類型中的申明順序相同,而與它們在建構函式的初始化列表中的順序無關。因此在這道題中,會首先初始化n1,而初始n1的參數n2還沒有初始化,是一個隨機值,因此n1就是一個隨機值。初始化n2時,根據參數0對其初始化,故n2=0。
參考資料:
程式員面試題精選100題
C++面試題(1-3)