【C++】 41_类型转换函数 (上)

发布时间:2019-06-14 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了【C++】 41_类型转换函数 (上)脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

再论类型转换

@H_126_4@
  • 标准数据类型之间会进行隐式的类型安全转换
  • clipboard.png

    实例分析: 有趣的隐式类型转换

    #include <iostream>
    
    using namespace std;
    
    int main()
    {
        short s = 'a';
        unsigned int ui = @H_360_58@1000;
        int i = -2000;
        double d = i;
        
        cout << "d = " << d << endl;
        cout << "i = " << i << endl;
        cout << "ui = " << ui << endl;
        cout << "ui + i = " << ui + i << endl;    // 注意这里!
        
        if( (ui + i) > 0 )                        // 注意这里!
        {
            cout << "Positive" << endl;
        }
        else
        {
            cout << "Negative" << endl;
        }
        
        cout << "sizeof(s + 'b') = " << sizeof(s + 'b') << endl;  // 注意这里!
    
        return 0;
    }
    输出:
    d = -2000
    i = -2000
    ui = 1000
    ui + i = 4294966296
    Positive
    sizeof(s + 'b') = 4
    

    分析 1:
    cout << "ui + i = " << ui + i << endl;
    if( (ui + i) > 0 ) {}

    ui 类型为 unsigned int; 
    i  类型为 int;
    操作数类型不一致,i 将发生隐式类型转换到 unsigned int ,内存中的二进制数将被重新解读。计算结果为 unsigned int 类型。
    

    分析 2:
    sizeof(s + 'b');

    s 类型为 short 
    'b' 类型为 char
    操作数类型不一致,s 将发生隐式类型转换到 int, 'b' 将发生隐式类型转换到 int。计算结果为 int 类型。
    

    问: 为什么不是 'b'(char) 隐式转换为 s (short) 类型呢?
    答: 4 字节整型数计算最高效

    问题

    普通类型与类类型之间能否进行类型转换?
    类类型之间能否进行类型转换?

    编程实验: 普通类型 -> 类类型

    #include <iostream>
    
    using namespace std;
    
    class Test
    {
    };
    
    int main()
    {
        Test t;
        
        t = 5;
        
        return 0;    
    }
    输出:
    test.cpp: In function ‘int main()’:
    test.cpp:13: error: no match foroperator=’ in ‘t = 5’
    test.cpp:6: note: candidates are: Test&amp; Test::operator=(const Test&)
    
    结论:
    编译器不支持普通类型到类类型的直接转换
    

    转换构造函数

    • 构造函数可以定义不同类型的参数
    • 参数满足下列条件时称为转换构造函数

      • 有且仅有一个参数
      • 参数是基本类型
      • 参数是其它类类型

    编程实验: 普通类型 -> 类类型

    #include <iostream>
    
    using namespace std;
    
    class Test
    {
    private:
        int mValue;
    public:
        Test()
        {
            cout << "Test()" << endl;
            mValue = 0;
        }
        Test(int i)
        {
            cout << "Test(int i), i = " << i << endl;
        
            mValue = i;
        }
        int value()
        {
            return mValue;
        }
        ~Test()
        {
            cout << "~Test(), mValue = " << mValue << endl;
        }
    };
    
    int main()
    {
        Test t;
        
        t = 5;                // 注意这里!
        
        cout << "t.value() = " << t.value() << endl;
        
        return 0;    
    }
    输出:
    Test()
    Test(int i), i = 5
    ~Test(), mValue = 5
    t.value() = 5
    ~Test(), mValue = 5
    
    

    编译器的行为

    • 编译器会尽力尝试码通过编译

    "5" 这个立即数默认为 int 类型,怎么可以赋值给 t 对象呢! 现在就报错吗?不急,我看看有没有转换构造函数! OK, 发现 Test 类中定义了 Test(int i),可以进行转换,默认等价于: t = Test(5) ,生成临时对象初始化 t ;

    t = 5; <--> t = Test(5);

    • 编译器尽力尝试的结果是隐式类型转换
    • 隐式类型转化

      • 会让程序以意想不到的方式进行工作
      • 是工程中 bug 的重要来源

    编程实验: 隐式转换的弊端

    #include <iostream>
    
    using namespace std;
    
    class Test
    {
    private:
        int mValue;
    public:
        Test()
        {
            mValue = 0;
        }
        Test(int i)
        {
            mValue = i;
        }
        Test operator + (const Test& p)
        {
            Test ret(mValue + p.mValue);
            
            return ret;
        }
        int value()
        {
            return mValue;
        }
    };
    
    int main()
    {
        Test t(5);
        
        t = t + 10;             // 注意这里!
        
        cout << "t.value() = " << t.value() << endl;
        
        return 0;    
    }
    输出:
    t.value() = 15
    

    应用层分析:
    类中重载了 + 操作符 Test operator + (const Test& p) , 可是右操作数参数类型为一个对象,为什么使用 整型值常量 可以进行相加操作呢? 是不是笔误? 编译器为什么没有报错呢?

    实质分析:
    t = t + 10; <--> t = t + Test(10); 编译器进行了隐式类型转换。

    结论:
    t = t + 10; t = 5; 尽量不使用这样的写法。可能笔误带来的书写,而编译器认为这种行为合法而导致问题。

    • 工程中通过 explicit 关键字杜绝编译器的尝试转换
    • 转换构造函数被 explicit 修饰时只能进行显示转换

    编程实验: explicit 尝试

    #include <iostream>
    
    using namespace std;
    
    class Test
    {
    private:
        int mValue;
    public:
        Test()
        {
            cout << "Test()" << endl;
            mValue = 0;
        }
        explicit Test(int i)
        {
            cout << "Test(int i), i = " << i << endl;
        
            mValue = i;
        }
        Test operator + (const Test& p)
        {
            Test ret(mValue + p.mValue);
            
            return ret;
        }
        int value()
        {
            return mValue;
        }
        ~Test()
        {
            cout << "~Test(), mValue = " << mValue << endl;
        }
    };
    
    int main()
    {
        Test t;
        
        t = static_cast<Test>(5);
        //t = Test(5);
        //t = (Test)5;
        
        cout << "t.value() = " << t.value() << endl;
        
        return 0;    
    }
    输出:
    Test()
    Test(int i), i = 5
    ~Test(), mValue = 5
    t.value() = 5
    ~Test(), mValue = 5
    
    分析:
    都会生成临时对象初始化 t
    

    小结

    • 转换构造函数只有一个参数
    • 转换构造函数的参数类型是其它类型
    • 转换构造函数在类型转换时被调用
    • 隐式类型转换是工程中 bug 的重要来源
    • explicit 关键字用于杜绝隐式类型转换

    以上内容参考狄泰软件学院系列课程,请大家保护原创

    脚本宝典总结

    以上是脚本宝典为你收集整理的【C++】 41_类型转换函数 (上)全部内容,希望文章能够帮你解决【C++】 41_类型转换函数 (上)所遇到的问题。

    如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

    本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
    如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。