06_C++强制转化
在桌面电脑普及的暗黑年代,人们使用的是键盘这种“神器”,一个dos一把键盘交互了整个系统。黑白字符的跳动,还正是我们所向往“牛逼的黑客”。Windows的伟大也不仅仅是微软的功劳。只是说解放了人们的头脑和双手,也是生产力的进步。更是人类发展趋势。MS或者说MS人,用自己的方式带来了变革。人永远会选择一种更为懒惰的方式来释放自己的欲望。来称呼其为社会进步。然而却掉入了别人了阴谋。
如果是我们觉得一种方式让自己觉得很不方便,我们会选择一个方式改进或者避开。
目前计算机体系运行还是基于内存地址(倚天剑)运行的一段预先编译好的程序。那么作为操作系统的神器,指针就是一把(屠龙刀),然而两者相遇左手内存右手指针,却不能触碰。只能是织女牛郎银河相望。
我们为了管理一大堆硬件,制作了一个管理员(OS)然后提供一个接口给操作员operater (coder) ,武林纷争谁不想有一把屠龙刀,称霸一方,给你一个指针横行于内存中,除了禁地。
C语言中常使用一段规划好的空间我们可以获取头指针,然后操作整个空间,但是数据有类型的。我们需要根据类型访问才能保证安全性。或者说是合法性。
定义一个指针
type* point;
定义一个指针变量point(或者说我们和系统or内存申请一个地址0x??? ??? 一个让我们可以被我们看到的一个名称point) 然后这只是在内存中的一个地址,我们可以用它来存储数据。只是类型是什么我们也不知道。但是其类型type规范了他的 能力,操作一个type
的数据类型。前提是合法的情况下。假设我们有一大段内存空间我们需要访问,拿到了这段空间的首地址,我们就可以用任何一个类型的指针来访问这段区间的数据,char
int
long
…自定义类型等等。 对于内存本身来说数据存储是没有任何意义的,只是人们在使用数据的时候是有意识的去区分类型,以达到我们所期望的目的。进而使用指针不同的方式,就会造成coder看到的数据不一样,可以int
访问一段空间也可以使用char
访问。但是也会带来分析风险—访问其他的数据。并破坏其他的的数据。这就是为什么屠龙刀和倚天剑天生不能在一起胡乱使用的原因。通常我们会在使用一段同类型的数据区域使用相同类型的指针来访问其数据,对于一段已知类型的地址空间(内存),我们也会使用相同的指针来访问其数据。避免数据的访问交错以及非法访问。这就会使用强制转换指针类型以达到上述目的。请看以下实现了该目标的错误使用方式。
#include <stdio.h>
typedef void(PF)(int);
struct Point
{
int x;
int y;
};
int main()
{
int v = 0x12345;
PF* pf = (PF*)v;
char c = char(v);
Point* p = (Point*)v;
pf(5);
printf("p->x = %d\n", p->x);
printf("p->y = %d\n", p->y);
return 0;
}
因为C语言对coder寄予期望是非常高的,你明白自己的操作指针方式以及目的,以及你知道你是面向内存编程的。但是开篇也说了人总是懒得,总想轻便,熟知鱼龙混杂的时代,又有多少人知道内存的对于系统的重要程度,但是又需要使用,所以那么久找一个更加安全方式来保证你的强制转换。
C++将强制转换分为四种不同类型:
static_cast
const_cast
reinterpret_cast
dynamic_cast
static_cast
用语基本类型间的转换;
不能用语基本类型指针间的转换;
用语有继承关系类型对象之间的转换和类指针之间的转换;
const_cast
用语去除变量的只读属性
强制转换的目标类型必须是指针或者引用
reinterpret_cast
用于指针类型间的强制转换
用于整数和指针类型间的强转换
dynamic_cast
用于有继承关系的类指针间的转换
用于有交叉关系的类指针间的转换
具有类型检查的功能
需要虚函数的支持
#include <stdio.h>
void static_cast_demo()
{
int i = 0x12345;
char c = 'c';
int* pi = &i;
char* pc = &c;
c = static_cast<char>(i);
pc = static_cast<char*>(pi);
}
void const_cast_demo()
{
const int& j = 1;
int& k = const_cast<int&>(j);
const int x = 2;
int& y = const_cast<int&>(x);
int z = const_cast<int>(x);
k = 5;
printf("k = %d\n", k);
printf("j = %d\n", j);
y = 8;
printf("x = %d\n", x);
printf("y = %d\n", y);
printf("&x = %p\n", &x);
printf("&y = %p\n", &y);
}
void reinterpret_cast_demo()
{
int i = 0;
char c = 'c';
int* pi = &i;
char* pc = &c;
pc = reinterpret_cast<char*>(pi);
pi = reinterpret_cast<int*>(pc);
pi = reinterpret_cast<int*>(i);
c = reinterpret_cast<char>(i);
}
void dynamic_cast_demo()
{
int i = 0;
int* pi = &i;
char* pc = dynamic_cast<char*>(pi);
}
int main()
{
static_cast_demo();
const_cast_demo();
reinterpret_cast_demo();
dynamic_cast_demo();
return 0;
}
C:\Users\SEELE\Desktop\QT\test\main.cpp:
11: error: invalid static_cast from type 'int*' to type 'char*'
pc = static_cast<char*>(pi);
^
C:\Users\SEELE\Desktop\QT\test\main.cpp:
22: error: invalid use of const_cast with type 'int', which is not a pointer, reference, nor a pointer-to-data-member type
int z = const_cast<int>(x);
^
C:\Users\SEELE\Desktop\QT\test\main.cpp:
47: error: invalid cast from type 'int' to type 'char'
c = reinterpret_cast<char>(i);
^
C:\Users\SEELE\Desktop\QT\test\main.cpp:
54: error: cannot dynamic_cast 'pi' (of type 'int*') to type 'char*' (target is not pointer or reference to class)
char* pc = dynamic_cast<char*>(pi);
^
k = 5
j = 5
x = 2
y = 8
&x = 0028FE9C
&y = 0028FE9C