第67课 经典问题解析五

1、指针的判别

    1.1、 拾遗
        1.1.1、 C++中仍然支持C语言中的可变参数函数
        1.1.2、 C++编译器的 匹配调用优先级 重载函数>函数模板>变参函数
    1.2、 思路
        1.2.1、 将变量分为两类: 指针 VS 非指针
        1.2.2、 编写函数:
                指针变量调用时回true
                 非指针变量 调用时返回 false     
    1.3、 函数模板与变参函数的化学反应
template<typename T>  //优先匹配函数模板

bool IsPtr(T* v) // match pointer
{
    return true;
}

//变参函数            //再匹配变参函数
bool IsPtr(...)  // match non-pointer
{
    return false;
}

                                        
/*********************判断这个变量是否为指针!************************/
#include <iostream>
#include <string>
using namespace std;
class Test
{
public:
    Test()
    {
    
    }
    virtual ~Test() //虚函数,子类重写,生成虚函数表
    {
    
    }
};
//模板函数-优先匹配
template <typename T>
char IsPtr(T* v)
{
    return 'd';         //返回值为:char型。
}

//变参函数-匹配的优先级比模板函数低,注意返回值与模板函数不同,这是因为当向变参函数中传入自定义类类型,才出现
int IsPtr(...)
{
    return 0;   //返回值为int型。
}

//定义这个宏的主要目的是,为了传自定义类型给可变参数时,可能出现的上述问题,可以利用sizeof来判断返回值的大小,如果为1表示char型,为匹配了模板函数。为4表示int型,匹配到了变参函数,从而区别变量到底是指针还是非指针类型,注意巧妙的利用了sizeof编译期就能确定的特性,从而避开运行期的错误。
#define ISPTR(p)  ((sizeof(IsPtr(p))) == (sizeof(char)))//编译期就能确定特性!!!(这种操作真的骚)
/*
template <typename T>
bool IsPtr(T* v)    //match pointer//函数模板匹配指针,
{
    return true;
}
bool IsPtr(...)     //match non-pointer//函数模板匹配非指针的。
{
    return false;
}
*/
int main()
{
    int i = 0;
    int* p = &i;
    
    cout << "i is a pointer  " << ISPTR(i) << endl;
    cout << "p is a pointer  " << ISPTR(p) << endl;
    
    //cout << "i is a pointer  " << IsPtr(i) << endl;
    //cout << "p is a pointer  " << IsPtr(p) << endl;
    
    Test t;
    Test* pt = &t;
    
    cout << "t is a pointer  " << ISPTR(t) << endl; // 对象
    cout << "pt is a pointer  " << ISPTR(pt) << endl;
    
    //cout << "pt is a pointer  " << IsPtr(pt) << endl;
    //cout << "t is a pointer  " << IsPtr(t) << endl;  //出错,可变参数检测不出来对象是什么类型。
    
    //因为C语言(兼容C语言)中的变参无法检测类是什么样的类型::
    //如果直接调用IsPtr来判断自定义类类型,会出现错误,
    //
    
    return 0;
}


                                  判断变量是否为指针的方案二
                /************   直接利用函数模板的重载  ***************/
#include <iostream>
#include <string>
using namespace std;
class Test
{
public:
    Test()
    {
    
    }
    virtual ~Test()
    {
    
    }
};
//模板函数
template <typename T>
bool IsPtr(T* v)
{
    return true;
}
template <typename T>
bool IsPtr(T v)
{
    return false;
}
int main()
{
    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;
    
    return 0;
}

    1.4、存在的缺陷及完善
        1.4.1、 变参函数 无法解析 自定义类类型的对象参数 ,可能造成程序崩溃
        1.4.2、 可以 在编译期 就精确匹配结果,而 不需等到实际调用IsPtr时才确定 。思路是通过sizeof,具体见例子中的注释。

2、 构造函数中的异常

    2.1、 当构造函数中抛出异常时
        2.1.1、 构造函数立即停止。
        2.1.2、 当前对象无法生成(譬如在堆空间上并不会生成地址。)
        2.1.3、 析构函数不会被调用
        2.1.4、 对象所占用的空间立即收回
    2.2、 工程项目中的建议
        2.2.1、 不要在构造函数中抛出异常 (注: 也可以在构造函数中try-catch可能的异常,并在异常发生时做善后的处理(如资源释放),最后再将这个异常抛出,以通知外部的函数。但建议不要这样做,因为有更好的二阶构造模式,二阶模式在内部自己处理了异常,而抛异常的方法是把异常处理再次丢给了外部的函数
        2.2.2、 当构造函数可能产生异常时,使用 二阶构造模式

                    /**********   构造中的异常   ***********/
#include <iostream>
#include <string>
using namespace std;
class Test
{
public:
    Test()
    {
        cout << "Test()..." << endl;
        throw 0;
    }
    ~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;
}       
//linux下可以用如下命令检查是否内存泄漏
// g++ -g 67-3.cpp
//  valgrind --tool=memcheck --leak-check=full ./a.out
                    

3、. 析构函数中的异常

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

4、 小结

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




















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值