- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章关于C++的强制类型转换浅析由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
前言 。
一说起强制类型转换大家都很熟悉,相信很多学习完C++的朋友还在使用C语言的强制类型的方式 (类型)变量. 。
C++其实也具有自己的一套强制类型转换它们分明是:static_cast reinterpret_cast const_cast dynamic_cast四种类型. 。
那么肯定会有人好奇C++是不是闲,C语言的强制类型用的舒舒服服的,为什么要新推出来这几个?
新类型的强制转换可以提供更好的控制强制转换过程,允许控制各种不同种类的强制转换。C++中风格是static_cast<type>。C++风格的强制转换其他的好处是,它们能更清晰的表明它们要干什么。程序员只要扫一眼这样的代码,就能立即知道一个强制转换的目 。
的.
static_cast 。
static_cast用于非多态类型的转换(静态转换),任何标准转换都可以用它,但它不能用于两个不相关的类型进行转换. 。
何为不相关类型? 比如int 和 double char short就是相关类型. 和int*就是不相关类型. 。
我们来看一看static_cast的用法. 例如,通过将一个运算对象强制转换成double类型就能使表达式执行浮点数除法:
1
|
double
slope =
static_cast
<
double
>(j) / i;
|
当static_cast需要把一个较大的算术类型赋值给较小的类型时,static_cast非常有用。此时,强制类型转换告诉程序的读者和编译器:我们知道并且不在乎潜在的精度损失。一般来说,如果编译器发现一个的算术类型试图赋值给较小的类型,就会给出警告信息;但是当我们执行了显式的类型转换后,警告信息就会被关闭了.
reinterpret_cast 。
reinterpret_cast有着和C风格的强制转换同样的能力。它可以转化任何内置的数据类型为其他任何的数据类型,也可以转化任何指针类型为其他的类型。它甚至可以转化内置的数据类型为指针,无须考虑类型安全或者常量的情形。不到万不得已绝对用.
因为reinterpret_cast是一个蛮bug的操作,下面我来演示一下. 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
typedef
void
(* FUNC)();
int
DoSomething (
int
i)
{
cout<<
"DoSomething"
<<endl;
return
0;
}
void
Test ()
{
// reinterpret_cast可以编译器以FUNC的定义方式去看待 DoSomething函数
// 所以非常的BUG,下面转换函数指针的代码是不可移植的,所以不建议这样用
// C++不保证所有的函数指针都被一样的使用,所以这样用有时会产生不确定的结果
FUNC f =
reinterpret_cast
< FUNC>(DoSomething );
f();
}
|
当你这样运行的时候,你会发现通过函数指针没有传参数调用这个有参数的函数居然可以调用,这就很尴尬了,所以我告诉你不到万不得已就不要使用reinterpret_cast 。
const_cast 。
对于将常量对象转化为非常量对象的行为,我们一般称之为“去掉const性质”。一旦我们去掉了某个对象的const性质,编译器就不再阻止我们对该对象进行写操作了。如果对象本身不是一个常量,使用强制类型转换获得写权限是合法的行为。然而如果对象是一个常量,再使用const_cast执行写操作就会产生未定义的后果.
举个例子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
#include<iostream>
#include<Windows.h>
#include<assert.h>
using
namespace
std;
int
main()
{
const
int
a = 2;
int
*p =
const_cast
<
int
*>(&a);
*p = 3;
cout << a << endl;
system
(
"pause"
);
return
0;
}
|
我们有理由的认为在内存当中a的值被修改为3,但是结果呢? 我们来看一看 。
这不科学啊?? 我们再打开监视窗口看一下a的值. 。
我们都知道监视窗口看到的都是从内存当中拿到的,但是为什么内存当中为3,打印出来就是2呢? 我来解释一下. 。
C++编译器具有优化功能,当你定一个const的常量的时候,系统觉得它不会被改变了,于是做一个优化把该常量存到寄存器当中,下次访问的过程更快速一点. 所以当显示窗口读取数据的时候,他会直接去寄存器当中读取数据.而不是去内存,所以导致我们明明该掉了a的值,却打印不出来,但是如何解决这个问题呢??
c++有一个关键字: volatile 该关键字的作用防止编译器优化,这个时候要输出a就会老老实实的回内存去查看. 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
#include<iostream>
#include<Windows.h>
#include<assert.h>
using
namespace
std;
int
main()
{
volatile
const
int
a = 2;
int
*p =
const_cast
<
int
*>(&a);
*p = 3;
cout << a << endl;
system
(
"pause"
);
return
0;
}
|
dynamic_cast 。
前三种的强制类型转换,他们能做到的C语言的强制类型转换也大多能做到,最后一种C语言的强制类型转换就没有办法了. 。
在类的转换时,在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的。在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。当用于多态类型时,它允许任意的隐式类型转换以及相反过程. 不过,与static_cast不同,在后一种情况里(注:即隐式转换的相反过程),dynamic_cast 会检查操作是否有效. 也就是说, 它会检查转换是否会返回一个被请求的有效的完整对象。检测在运行时进行. 如果被转换的指针不是一个被请求的有效完整的对象指针,返回值为NULL. 对于引用 类型,会抛出bad_cast异常 。
你说这个强转有啥用,其实对于我这种菜鸟还真的没用过,不过我知道一个问题可以使用这样的方法解决. 给你两个类让你分辨那个是子类那个是父类,我们来看看是如何解决的. 。
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
47
48
49
50
51
52
53
54
55
56
57
|
#include<iostream>
#include<Windows.h>
#include<assert.h>
using
namespace
std;
class
AA
{
public
:
virtual
void
fun1()
{
cout <<
"hehe"
<< endl;
}
public
:
int
a;
};
class
BB :
public
AA
{
public
:
virtual
void
fun1()
{
cout <<
"heh2e"
<< endl;
}
public
:
int
c;
};
int
main()
{
AA* q =
new
AA();
BB* p =
new
BB();
AA* a;
BB* b;
b =
dynamic_cast
<BB*>(q);
if
(b == NULL)
{
cout <<
"AA为基类"
<< endl;
}
else
{
cout <<
"AA为子类"
<< endl;
}
a =
dynamic_cast
<AA*>(p);
if
(a == NULL)
{
cout <<
"BB为基类"
<< endl;
}
else
{
cout <<
"BB为子类"
<< endl;
}
system
(
"pause"
);
return
0;
}
|
总结 。
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我的支持.
原文链接:http://blog.csdn.net/dawn_sf/article/details/77914861 。
最后此篇关于关于C++的强制类型转换浅析的文章就讲到这里了,如果你想了解更多关于关于C++的强制类型转换浅析的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我一直很难编辑我的 .htaccess 文件来一起做这三件事。我已经能够分别获得每个部分,但我只是不明白逻辑流程如何使它们全部工作。 这是我能够使用 bluehost support 上的演示进行整合
我制作的宏将模板工作簿保存为两个单独的文件。每个测试保存一个(位置 1、2、3 或 4),然后在另一个宏中使用每个测试的数据。第二个是保留用于备份的原始数据文件。现在的问题是每次我在每个位置运行测试并
我正在写一篇关于如何使用 OCaml 的模块系统而不是 Java 的 OO 系统(一个有趣的视角)的博客文章。我遇到了一些我不理解的关于强制的事情。下面是一个基本模块和两个包含它的模块: module
我有一段将被执行多次(5,000+)的代码,以及一个仅在第一次为真的 if 语句。我曾想过使用“FIRST”变量并每次都进行比较,但每次都检查它似乎是一种浪费,即使我知道它不需要。 bool FIRS
首先,我是 Perforce 的新手,我主要通过其文档进行学习。 因此,我们即将从 CVS 迁移到 Perforce,我最近学到了一个避免更改每个工作区的 P4CLIENT 的好方法,即在工作区根目录
我正在为一段代码编写测试,其中包含我试图涵盖的 IOException 捕获。 try/catch 看起来像这样: try { oos = new ObjectOutputStream(new
我正在尝试在新闻项目滚动之间添加延迟。我知道 $.each() 通过不等待动画完成来完成其工作,但我想知道如何制作它,以便一次向上滚动一个项目并等到最后一个动画完成后再继续在循环中。 $(functi
假设已经编写了一个方法,需要一个排序列表作为其输入之一。当然这将在代码中进行注释和记录,param 将被命名为“sortedList”,但如果有人忘记,则会出现错误。 有没有办法强制输入必须排序?我正
我正在尝试将传入请求重定向到 https://www.domain.com/和所有 https://www.domain.com/ {所有页面}并且没有什么麻烦。我试过的方法: 添加此行:Redire
我将如何实现以下内容: title_selection = raw_input("Please type in the number of your title and press Enter.\n%
我有一个登录表单,我需要强制关闭自动完成功能。我试过了 jquery: $('#login').attr("autocomplete", "off"); HTML: Javascript:docume
我想知道我应该怎么做才能强制从 dev 分支 merge 到我的 master 分支?使用“git merge dev”会导致很多冲突。但是,我不想单独处理它们。相反,我只是想使用我的 dev 分支中
当安装 Hl7.Fhir.DSTU2 和 Hl7.Fhir.R4 这两个 Nuget 包时,我们得到如下信息: DSTU2 包似乎在使用 Hl7.Fhir.Support.Poco 版本 3.4.0
我正在尝试让一个功能组件在 testFn 执行时强制重新渲染。我想使用状态来做到这一点(如果有更好的方法请说出来),这似乎成功地强制重新渲染但只有两次,然后什么都没有。 我构建了一个简单的演示来模拟这
默认情况下,g++ 似乎会省略未使用的类内定义方法的代码。示例 from my previous question : struct Foo { void bar() {} void baz(
我正在尝试使用 here 中介绍的技术使我的网站背景以比内容慢的速度滚动。我不希望背景固定,只希望更慢。 这是 HTML 的样子: .parallax { perspective: 1px;
我能找到的最相似的问题是 'how to create a row of scrollable text boxes or widgets in flutter inside a ListView?'
我有以下 eslint 配置: "object-curly-newline": ["error", { "ImportDeclaration": "never",
我正在使用 TinyMCE 插件并将 valid_elements 选项设置为: "a[href|target:_blank],strong/b,em/i,br,p,ul,ol,li" 即使没有列出数
您好,我想使用以下命令放置多行描述 p4 --field Description="MY CLN Header \\n my CLN complete description in two -thre
我是一名优秀的程序员,十分优秀!