67、经典问题解析5

编写程序判断一个变量是不是指针。

拾遗: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>
char IsPtr(T* v) // match pointer  //在宏sizeof(只匹配不调用)之前是bool, return true
{
    return 'd';

}

int IsPtr(...)  // match non-pointer  //在宏sizeof()之前是bool,return false
{
    return 0;

}

#define ISPTR(p) (sizeof(IsPtr(p)) == sizeof(char))  //宏名字ISPTR,接收一个参数p

                                                                              //判断调用IsPtr过后,返回值类型占用多大内存,假设用一个指针使用宏,  //编译器做实际的匹配,匹配到第一个函数,编译器在编译期间就能确认函数调用返回char,不用调用这个函数

int main(int argc, char *argv[])
{
    int i = 0;
    int* p = &i;    
    cout << "p is a pointer: " << ISPTR(p) << endl;    // true

    cout << "i is a pointer: " << ISPTR(i) << endl;    // false    

//自定义类类型

    Test t;
    Test* pt = &t;    
    cout << "pt is a pointer: " << ISPTR(pt) << endl;    // true

    cout << "t is a pointer: " << ISPTR(t) << endl;    // false

    //存在的缺陷,变参函数无法解析对象参数,可能造成程序崩溃,如何让编译器精确匹配函数,但不进行实际的调用?

   //非法指令,对象调用会匹配到变参函数,变参函数是C语言中的特色,不知                                                                              //道对象是什么,传过去的是对象,涉及到构造,拷贝构造,析构

    return 0;
}

2、如果在构造函数中抛出异常会发生什么情况?

构造函数抛出异常:构造过程立即停止,当前对象无法生成,析构函数不会被调用,对象所占用的空间立即收回。

工程项目中的建议:不要在构造函数中抛出异常,当构造函数可能产生异常时,使用二阶构造模式。

#include <iostream>
#include <string>
using namespace std;
class Test
{
public:
    Test()
    {
        cout << "Test()" << endl;        
        throw 0;
    }
    virtual ~Test()
    {
        cout << "~Test()" << endl;
    }
};
int main(int argc, char *argv[])
{
    Test* p = reinterpret_cast<Test*>(1);    
    try
    {
        p = new Test();
    }
    catch(...)
    {
        cout << "Exception..." << endl;
    }    
    cout << "p = " << p << endl;    
    return 0;
}
//结果:没有调用析构函数,p指针还是0x1,没有内存泄漏

//没有抛异常运行会内存泄漏,有new却没有delete,析构函数是析构对象的,不是析构new的

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

利用函数模板和变参函数能够判断指针变量。构造函数和析构函数不要抛出异常,不可避免的话二阶构造。

猜你喜欢

转载自blog.csdn.net/ws857707645/article/details/80294505