博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【C++】 41_类型转换函数 (上)
阅读量:6830 次
发布时间:2019-06-26

本文共 4020 字,大约阅读时间需要 13 分钟。

再论类型转换

  • 标准数据类型之间会进行隐式的类型安全转换

clipboard.png

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

#include 
using namespace std;int main(){ short s = 'a'; unsigned int ui = 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 = -2000i = -2000ui = 1000ui + i = 4294966296Positivesizeof(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 
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 for ‘operator=’ in ‘t = 5’test.cpp:6: note: candidates are: Test& Test::operator=(const Test&)结论:编译器不支持普通类型到类类型的直接转换

转换构造函数

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

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

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

#include 
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 = 5t.value() = 5~Test(), mValue = 5

编译器的行为

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

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

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

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

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

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

#include 
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 修饰时只能进行显示转换

    • 转换方式

      • static_cast<ClassName>(value);
      • ClassName(value);
      • (ClassName)value; // 不推荐

编程实验: explicit 尝试

#include 
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
(5); //t = Test(5); //t = (Test)5; cout << "t.value() = " << t.value() << endl; return 0; }
输出:Test()Test(int i), i = 5~Test(), mValue = 5t.value() = 5~Test(), mValue = 5分析:都会生成临时对象初始化 t

小结

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

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

转载地址:http://fvnkl.baihongyu.com/

你可能感兴趣的文章
资料收集 不断更新
查看>>
ubuntu下安装LNMP
查看>>
各种小细节
查看>>
PHP 5 安装配置(版本大于等于 5.3)
查看>>
对SEO网站优化使用技巧的总结
查看>>
yolov3 darknet:parser.c:315: failed
查看>>
如何关闭SELinux
查看>>
安全工具Nmap扫描参数解析(转)
查看>>
将阿里域名配置保存到execl文件(后面将使用到本地数据库平台等)
查看>>
c# DateTime 时间
查看>>
【码云周刊第 48 期】Eclipse 常用的高效插件
查看>>
SNMP故障问题解决方法
查看>>
网络MSDTC(分布式事务处理协调器)服务配置方法
查看>>
比尔·盖茨的 33 年及名言集锦 - 为比尔送行、鼓掌!
查看>>
System 提供的编译期函数
查看>>
简单读取网上的文本文件
查看>>
【Spring】浅谈ContextLoaderListener及其上下文与DispatcherServlet的区别
查看>>
Css中display属性和其它测试
查看>>
多重 nginx 反向代理获取客户端真实 ip
查看>>
函数嵌套(c++)
查看>>