• 67 - 经典问题解析五(指针的判别 & 构造中的异常)


    ---- 整理自狄泰软件唐佐林老师课程

    1. 问题一

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

    1.1 指针的判别

    • C++中仍然支持C语言中的可变参数函数
    • C++编译器的 匹配调用 优先级重载函数 > 函数模板 > 变参函数
    #include 
    #include 
    using namespace std;
    
    void test(int i) {
        cout << "void test(int i)" << endl;
    }
    
    template
    <typename T>
    void test(T v) {
        cout << "void test(T v)" << endl;
    }
    
    void test(...) {
        cout << "void test(...)" << endl;
    }
    
    int main(int argc, char *argv[]) {
        int i = 0;
    
        test(i);
        
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    在这里插入图片描述

    1.2 思路

    将变量分为两类:指针 VS 非指针

    • 编写函数:
      指针变量调用时返回true
      非指针变量调用时返回false

    1.3 函数模板与变参函数的化学反应

    在这里插入图片描述

    根据参数的匹配,返回true就是指针,变参函数返回false就不是指针。

    1.4 编程实验:指针判断

    在这里插入图片描述
    在这里插入图片描述

    1.5 存在的缺陷

    变参函数无法解析对象参数,可能造成程序崩溃

    • 如何让编译器精确匹配函数,但不进行实际的调用?只去进行匹配而不运行?
    #include 
    #include 
    
    using namespace std;
    
    class Test
    {
    public:
        Test()
        {
        }
        virtual ~Test()
        {
        }
    };
    
    template
    <typename T>
    char IsPtr(T* v) // match pointer
    {
        return 'd';
    }
    
    int IsPtr(...)  // match non-pointer
    {
        return 0;
    }
    
    #define ISPTR(p) (sizeof(IsPtr(p)) == sizeof(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
        
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    在这里插入图片描述

    • 注解: 编译器 编译阶段 根据参数类型,判断使用哪个函数,sizeof可以根据函数类型给出相应计算结果(没有调用函数)。

    2. 问题二

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

    2.1 构造函数中抛出异常

    • 构造过程立即停止
    • 当前对象无法生成
    • 析构函数不会被调用
    • 对象所占用的空间立即收回

    2.2 工程项目中的建议

    不要在构造函数中抛出异常
    当构造函数可能产生异常时,使用二阶构造模式

    2.3 编程实验:构造中的异常

    #include 
    #include 
    
    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    在这里插入图片描述

    注:reinterpret 是“重新解释”的意思,顾名思义,reinterpret_cast 这种转换仅仅是对二进制位的重新解释,不会借助已有的转换规则对数据进行调整,非常简单粗暴。
    http://c.biancheng.net/view/2343.html

    2.4 析构中的异常

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

    3. 小结

    • C++中依然支持变参函数
    • 变参函数无法很好的处理对象参数
    • 利用函数模板和变参函数能够判断指针变量
    • 构造函数和析构函数中不要抛出异常
  • 相关阅读:
    Docker-compose部署XWiki
    vue独立提供模板下载功能
    五、资源控制器
    Kubernetes CKA 模拟题解析【2022最新版】(连载001)
    隆重推出 Incredibuild 10
    湖仓一体电商项目(十二):编写写入DM层业务代码
    Asp.Net Core webapi+net6 使用资源筛选器(过滤器) 做缓存
    9月15日第壹简报,星期四,农历八月二十
    flex&bison系列第二章:写一个简单的单词统计工具Word Counter
    数据结构——C语言实现String字符串操作
  • 原文地址:https://blog.csdn.net/weixin_36098975/article/details/128116787