下来我们就来试着编写下这个函数
#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。
原文地址:http://blog.51cto.com/12810168/2125283