67_经典问题解析五

1. 面试题:编写程序判断一个变量是不是指针。

拾遗

  • C++中仍然支持C语言中的可变参数函数
  • C++编译器的匹配调用优先级
    (1) 重载函数
    (2) 函数模板
    (3) 变参函数

思路:
将变量分为两类:指针 vs 非指针
编写函数:
指针变量调用时返回true
非指针变量调用时返回false
通过函数模板变参函数的结合:

67_经典问题解析五_第1张图片

编程说明:指针判断解决方案初步尝试

#include 
#include 

using namespace std;

class Test
{
public:
    Test()
    {
    }
    
    virtual ~Test()
    {
    }
};

template

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 
#include 

using namespace std;

class Test
{
public:
    Test()
    {
    }
    
    virtual ~Test()
    {
    }
};

template

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 
#include 

using namespace std;

class Test
{
public:
    Test()
    {
        cout << "Test()" << endl;
        throw 0;
    }
    
    virtual ~Test()
    {
        cout << "virtual ~Test()" << endl;
    }
};

int main()
{
    Test* p = reinterpret_cast(1);
    
    cout << "p = " << p << endl;
    
    try
    {
        p = new Test();
    }
    catch(...)
    {
        cout << "Exception ..." << endl;
    }
    
    return 0;
}

输出结果:

p = 0x1
Test()
Exception ...

3. 面试题:析构函数中抛出异常会发生什么情况?

析构函数的异常将导致:对象所使用的资源无法完全释放
因此:避免在析构函数中抛出异常

4. 小结

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

你可能感兴趣的:(67_经典问题解析五)