在面試中有可能會遇到這個面試題,編寫程序判斷一個變量是否是指針。咱們咋一看是否是有點懵逼,咱們能夠想到利用 C 語言中的可變參數函數。在 C++ 中依然是支持的,C++ 編譯器的匹配調用優先級是:一、重載函數;二、函數模板;三、變參函數。咱們能夠將變量分爲兩類:指針和非指針。須要編寫函數的功能是當是指針變量調用時便返回 true,是非指針變量調用時返回 false。ios
下來咱們就來試着編寫下這個函數面試
#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; }
咱們利用函數模板和可變參數函數來實現,下來看看編譯結果是否是咱們所指望的ide
咱們看到已經實現了,因而滿意的交給了面試官。面試官看了下,笑着說你這個程序對通常的數據類型是可行的,對於類類型仍是進行判斷嘛?咱們接着來試下類類型的判斷是否還可行,在程序中添加一個類,再生成一個類對象 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; }
咱們再次編譯看看結果spa
咱們看到已經編譯經過了,而且也正確進行類對象類型的判斷了。那麼這個面試題咱們就完美的進行回答了。還有一個面試題:若是在構造函數中拋出異常會發生什麼?這便綜合考查到了咱們的基礎知識了,涉及到對象的構造、異常以及其餘方面的知識。那麼在構造函數中拋出異常,最直接的影響就是構造過程會當即中止,那麼當前的對象便沒法生成了。因爲是異常,析構函數一樣也沒法被調用了,對象所佔用的空間會當即收回。那麼在工程項目中的建議是:不要在構造函數中拋出異常,當構造函數可能產生異常時,咱們便要使用二階構造模式。指針
下來咱們仍是以代碼爲例來進行分析對象
#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,證實並無對象的生成。咱們應避免在析構函數中拋出異常!!析構函數的異常將致使對象所使用的資源沒法徹底釋放。經過對一些經典問題的學習,總結以下:一、C++ 中依然支持變參函數;二、變參函數沒法很好的處理對象參數;三、利用函數模板和變參函數可以判斷指針變量;四、構造函數和析構函數中不要拋出異常。資源
歡迎你們一塊兒來學習 C++ 語言,能夠加我QQ:243343083。