經典問題解析五(五十五)
下來我們就來試著編寫下這個函數
#include <iostream> #include <string> using namespace std; template < typename T > bool IsPtr(T* v) { return true; } bool IsPtr(...) { return false; } int main() { int i = 0; int* p = &i; cout << "p is a pointer: " << IsPtr(p) << endl; cout << "i is a pointer: " << IsPtr(i) << endl; return 0; }
我們利用函數模板和可變參數函數來實現,下來看看編譯結果是不是我們所期望的
我們看到已經實現了,於是滿意的交給了面試官。面試官看了下,笑著說你這個程序對一般的數據類型是可行的,對於類類型還是進行判斷嘛?我們接著來試下類類型的判斷是否還可行,在程序中添加一個類,再生成一個類對象 t,指向類對象 t 的指針 pt,下來看看編譯結果
我們看到編譯直接報錯了,也就是說對於類對象來說並不行,變參函數無法解析對象參數。那麽我們想想怎麽辦呢,既然不能直接 IsPtr 函數的調用,我們還可以利用它的返回值類型的大小來進行判斷,將模板函數的返回值類型設置為 char,返回一個字符;將全局函數的返回值類型設置為 int,直接返回 0。再定義一個宏用來判斷函數 IsPtr 的返回值是不是等於 char 類型的大小,如果是則返回 1,否則返回 0
#include <iostream> #include <string> using namespace std; class Test { public: Test() { } virtual ~Test() { } }; template < typename T > char IsPtr(T* v) { return 'c'; } int IsPtr(...) { return 0; } #define ISPTR(p) (sizeof(IsPtr(p)) == sizeof(char)) int main() { int i = 0; int* p = &i; cout << "p is a pointer: " << ISPTR(p) << endl; cout << "i is a pointer: " << ISPTR(i) << endl; cout << endl; Test t; Test* pt = &t; cout << "pt is a pointer: " << ISPTR(pt) << endl; cout << "t is a pointer: " << ISPTR(t) << endl; return 0; }
我們再次編譯看看結果
我們看到已經編譯通過了,並且也正確進行類對象類型的判斷了。那麽這個面試題我們就完美的進行回答了。還有一個面試題:如果在構造函數中拋出異常會發生什麽?這便綜合考查到了我們的基礎知識了,涉及到對象的構造、異常以及其他方面的知識。那麽在構造函數中拋出異常,最直接的影響就是構造過程會立即停止,那麽當前的對象便無法生成了。由於是異常,析構函數同樣也無法被調用了,對象所占用的空間會立即收回。那麽在工程項目中的建議是:不要在構造函數中拋出異常,當構造函數可能產生異常時,我們便要使用二階構造模式。
下來我們還是以代碼為例來進行分析
#include <iostream> #include <string> using namespace std; class Test { public: Test() { cout << "Test()" << endl; throw 0; } virtual ~Test() { cout << "~Test()" << endl; } }; int main() { Test* p = reinterpret_cast<Test*>(1); try { p = new Test(); } catch(...) { cout << "Exception..." << endl; } cout << "p = " << p << endl; return 0; }
我們在構造函數先打印函數名,在進行異常的拋出。先將指針 p 指向地址為 1 處,如果對象生成,那麽便會返回一個地址值。我們來看看編譯結果
在拋出異常後,我們看到 p 的地址還是為 1,證明並沒有對象的生成。我們應避免在析構函數中拋出異常!!析構函數的異常將導致對象所使用的資源無法完全釋放。通過對一些經典問題的學習,總結如下:1、C++ 中依然支持變參函數;2、變參函數無法很好的處理對象參數;3、利用函數模板和變參函數能夠判斷指針變量;4、構造函數和析構函數中不要拋出異常。
歡迎大家一起來學習 C++ 語言,可以加我QQ:243343083。
經典問題解析五(五十五)