类型转换函数

  • 论类型转换
  1. 标准数据类型之间会进行隐式的类型安全转换
  2. 转换规则如下所示:
               char  ===>int ==>unsigned int ==>long ==>unsigned long ==>float ==>double
                 ||         ||
                 V         ||
               short===
  • 例:
 1 // 类型转换函数.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
 2 //
 3 #include <iostream>
 4 #include <string>
 5 using namespace std;
 6 int main()
 7 {
 8     int a = -2000;
 9     unsigned int b = 1000;
10     short c = 'A';
11     cout << "sizeof(c+'B')=" << sizeof(c + 'B') << endl;
12     cout << "a+b=" << a + b << endl;
13     if ((a+b)>0)
14     {
15         cout << "Positive" << endl;
16     }
17     else
18     {
19         cout << "Nagitve" << endl;
20     }
21 }
运行结果:
sizeof(c+'B')=4
a+b=4294966296
Positive
从程序的运行结果来看,我们会发现两个问题
问题1:sizeof(c+'B')结果为什么为4,不应该是两个字节吗?
问题2:从数学的角度看,-2000+1000不应该是-1000吗?为什么结果为正?
答1:c的类型为short类型,占两个字节,程序在编译时将'A'优化隐式类型转换为short类型
答2::a的类型为int类型,程序在编译时会将其隐式转换成unsigned int类型
 
请看下面的程序:
 1 // 类型转换函数.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
 2 //
 3 #include <iostream>
 4 #include <string>
 5 using namespace std;
 6 class Test
 7 {
 8     int mvalue;
 9 public:
10     Test()
11     {
12         mvalue = 0;
13     }
14     Test(int i)
15     {
16         mvalue = i;
17     }
18     Test operator +(const Test& obj)
19     {
20         Test ret(mvalue+obj.mvalue);
21         return ret;
22     }
23     int get_value()
24     {
25         return mvalue;
26     }
27 };
28 int main()
29 {
30     Test t(5);
31     cout << "t.mvalue=" << t.get_value() << endl;
32     t = 10;
33     cout << "t.mvalue=" << t.get_value() << endl;
34 }
t=10;这条语句,会发现一个问题,10为整型数据,它怎么可以给一个对象赋值呢?更加诡异的是,编译竟然通过,且可以正常运行!
 
再论构造函数
  • 构造函数可以定义不同类型的参数
  • 参数满足下列条件时称为转换构造函数
  1. 有且仅有一个参数
  2. 参数是基本类型
  3. 参数是其它类类型
从另一个视角看:
  • 旧式的C方式强制类型转换
int i;
Test t;
i = int(1.5);
t = Test(100);
编译器是怎么看待t=10呢??
“10这个立即数默认为int类型,怎么可能赋值给t对象呢!现在就报错吗?不急,我看看有没有转换构造函数!OK,发现Test类中定义了Test(int i),可以进行转换,默认等价于:t = Test(100);"
  • 编译器的行为
  1. 编译器尽力尝试的结果是隐式类型转换
  2. 隐式类型转换会让程序以意想不到的方式进行工作,是工程中bug的重要来源。
  3. 在工程中通过explicit关键字杜绝编译器的转换尝试
  4. 转换构造函数被explicit修饰时只能进行显示转换
  • 转换方式
  1. static_cast<ClassName>(value);
  2. ClassName(value);
  3. (ClassName)value; //不推荐
进行强制类型转换,正确写法如下:
// 类型转换函数.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <string>
using namespace std;
class Test
{
    int mvalue;
public:
    Test()
    {
        mvalue = 0;
    }
    explicit Test(int i)
    {
        mvalue = i;
    }
    Test operator +(const Test& obj)
    {
        Test ret(mvalue+obj.mvalue);
        return ret;
    }
    int get_value()
    {
        return mvalue;
    }
};
int main()
{
    Test t(5);
    cout << "t.mvalue=" << t.get_value() << endl;
    t =static_cast<Test>(10);
    cout << "t.mvalue=" << t.get_value() << endl;
 
}
思考:类类型是否能够类型转换到普通类型??
类型转换函数
  1. C++类中可以定义类型转换函数
  2. 类型转换函数用于将类对象转换为其它类型
  3. 语法规则:
operator Type()
{
    Type ret;
    //....
    return ret;
}
例:
// 类型转换函数.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <string>
using namespace std;
class Test
{
    int mvalue;
public:
    Test()
    {
        mvalue = 0;
    }
    //转换构造函数
    explicit Test(int i)
    {
        mvalue = i;
    }
    //类型转换函数
    operator int()
    {
        int ret;
        ret = mvalue;
        return ret;
    }
    Test operator +(const Test& obj)
    {
        Test ret(mvalue+obj.mvalue);
        return ret;
    }
    int get_value()
    {
        return mvalue;
    }
};
int main()
{
    Test t(5);
    cout << "t.mvalue=" << t.get_value() << endl;
    t =static_cast<Test>(10);
    cout << "t.mvalue=" << t.get_value() << endl;
    
    int i = t;
    cout << "i=" << i << endl;
}
  • 类型转换函数
  1. 与转换构造函数具有同等的地位
  2. 使得编译器有能力将对象转化为其它类型
  3. 编译器能够隐式的使用类型转换函数
  • 编译器会尽力尝试让源码通过编译( int i = t;)
       “t这个对象为Test类型,怎么可能用于初始化int类型的变量呢!现在就报错吗不急,我看看有没有类型转换函数!OK,发现了Test类中定义了operator int(),可以进行转换”
  • 类类型之间的相互转换(类型转换函数VS转换构造函数)
  1. 无法抑制隐式的类型转换函数调用
  2. 类型转换函数可能与转换构造函数冲突
  3. 工程中Type to Type的公有成员代替类型转换函数
// 类型转换函数.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <string>
using namespace std;
class value
{
    int _val;
public:
    value()
    {
        _val = 0;
    }
    value(int i)
    {
        _val = i;
    }
    int get_value()
    {
        return _val;
    }
};
class Test
{
    int mvalue;
public:
    Test()
    {
        mvalue = 0;
    }
    //转换构造函数
    explicit Test(int i)
    {
        mvalue = i;
    }
    //类型转换函数
    operator int()
    {
        int ret;
        ret = mvalue;
        return ret;
    }
    //类类型之间的转换
    operator value()
    {
        value ret(mvalue);
        return ret;
    }
    Test operator +(const Test& obj)
    {
        Test ret(mvalue+obj.mvalue);
        return ret;
    }
    int get_value()
    {
        return mvalue;
    }
};
int main()
{
    Test t(5);
    value v(9);
    cout << "t.mvalue=" << t.get_value() << endl;
    t =static_cast<Test>(100);
    cout << "t.mvalue=" << t.get_value() << endl;
    
    int i = t;
    cout << "i=" << i << endl;
    //类类型之间的转换
    v = t;
    cout << "v._val=" << v.get_value() << endl;
}
运行结果:
t.mvalue=5
t.mvalue=100
i=100
v._val=100
 
使用Type toType()的公有成员代替类型转换函数
// 类型转换函数.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <string>
using namespace std;
class Test;
class value
{
    int _val;
public:
    value()
    {
        _val = 0;
    }
    value(int i)
    {
        _val = i;
    }
    int get_value()
    {
        return _val;
    }
};
class Test
{
    int mvalue;
public:
    Test()
    {
        mvalue = 0;
    }
    //转换构造函数
    explicit Test(int i)
    {
        mvalue = i;
    }
    //类型转换函数
    operator int()
    {
        int ret;
        ret = mvalue;
        return ret;
    }
    //类类型之间的转换
    operator value()
    {
        value ret(mvalue);
        return ret;
    }
    //使用Type toType()来代替类型转换函数
    int toINT()
    {
        int ret;
        ret = mvalue;
        return ret;
    }
    Test operator +(const Test& obj)
    {
        Test ret(mvalue + obj.mvalue);
        return ret;
    }
    int get_value()
    {
        return mvalue;
    }
};
int main()
{
    Test t(5);
    value v(9);
    cout << "t.mvalue=" << t.get_value() << endl;
    t =static_cast<Test>(100);
    cout << "t.mvalue=" << t.get_value() << endl;
    
    int i = t;
    cout << "i=" << i << endl;
    //类类型之间的转换
    v = t;
    cout << "v._val=" << v.get_value() << endl;
    //使用类中的公有成员函数进行类型转换
    int x = t.toINT();
    cout << "x=" << x << endl;
}
运行结果:
t.mvalue=5
t.mvalue=100
i=100
v._val=100
x=100
 
 
小结:
  1. 转换构造函数只有一个参数
  2. 转换构造函数的参数类型是其它类型
  3. 转换构造函数在类型转换时被调用
  4. 隐式类型转换是工程中bug的重要来源
  5. explicit关键字用于杜绝隐式类型转换
  6. C++类中可以定义类型转换函数
  7. 类型转换函数用于将类对象转换为其它类型
  8. 类型转换函数与转换构造函数具有同等的地位
  9. 工程中以Type toType()的公有成员代替类型转换函数
 
 
 
 
posted @ 2020-01-28 21:10  认真做个普通人  阅读(415)  评论(0编辑  收藏  举报