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++中依然支持变参函数
- 变参函数无法很好的处理对象参数
- 利用函数模板和变参函数能能够判断指针变量
- 构造函数和析构函数中不要抛出异常