1. 面試題:編寫程序判斷一個變量是不是指針。
拾遺
- C++中仍然支持C語言中的可變參數函數
- C++編譯器的匹配調用優先級
(1) 重載函數
(2) 函數模板
(3) 變參函數
思路:
將變量分為兩類:指針 vs 非指針
編寫函數:
指針變量調用時返回true
非指針變量調用時返回false
通過函數模板和變參函數的結合:
編程說明:指針判斷解決方案初步嘗試
#include <iostream>
#include <string>
using namespace std;
class Test
{
public:
Test()
{
}
virtual ~Test()
{
}
};
template
<typename T>
bool IsPtr(T* t)
{
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 NOT a pointer : " << IsPtr(i) << endl;
Test t;
Test* pt = &t;
cout << "pt is a pointer : " << IsPtr(pt) << endl;
// cout << "t is NOT a pointer : " << IsPtr(t) << endl; // error
return 0;
}
輸出結果:
p is a pointer : 1
i is NOT a pointer : 0
pt is a pointer : 1
存在問題:
IsPtr(t)
報錯:cannot pass objects of non-trivially-copyable type ‘class Test’ through ‘...’
問題分析:變參函數源自于C語言,是否支持對象的解析。
進一步優化:如何讓編譯器精確匹配函數,但不進行實際的調用?
編程說明:指針判斷解決方案完成版
#include <iostream>
#include <string>
using namespace std;
class Test
{
public:
Test()
{
}
virtual ~Test()
{
}
};
template
<typename T>
char IsPtr(T* t)
{
return 'd';
}
int IsPtr(...)
{
return 0;
}
// sizeof是編譯器內置指示符,因此,下面的 == 在編譯期就會完成
#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 NOT a pointer : " << ISPTR(i) << endl;
Test t;
Test* pt = &t;
cout << "pt is a pointer : " << ISPTR(pt) << endl;
cout << "t is NOT a pointer : " << ISPTR(t) << endl; // error
return 0;
}
輸出結果:
p is a pointer : 1
i is NOT a pointer : 0
pt is a pointer : 1
t is NOT a pointer : 0
2. 面試題:如果構造函數中拋出異常會發生什么情況?
構造函數中拋出異常:
(1) 構造過程立即停止
(2) 當前對象無法生成
(3) 析構函數不會被調用
(4) 對象所占的空間立即收回
工程項目中的建議:
(1) 不要在構造函數中拋出異常
(2) 當構造函數可能產生異常時,使用二階構造模式
編程說明:構造中的異常
#include <iostream>
#include <string>
using namespace std;
class Test
{
public:
Test()
{
cout << "Test()" << endl;
throw 0;
}
virtual ~Test()
{
cout << "virtual ~Test()" << endl;
}
};
int main()
{
Test* p = reinterpret_cast<Test*>(1);
cout << "p = " << p << endl;
try
{
p = new Test();
}
catch(...)
{
cout << "Exception ..." << endl;
}
return 0;
}
輸出結果:
p = 0x1
Test()
Exception ...
3. 面試題:析構函數中拋出異常會發生什么情況?
析構函數的異常將導致:對象所使用的資源無法完全釋放。
因此:避免在析構函數中拋出異常
4. 小結
- C++中依然支持變參函數
- 變參函數無法很好的處理對象參數
- 利用函數模板和變參函數能能夠判斷指針變量
- 構造函數和析構函數中不要拋出異常