文章目录
- 学习目标:
- 1.static_cast
- 2. reinterpret_cast
- 3.const_cast
- 4. dynamic_cast
- 学习过程
- 1.static_cast
- 2. reinterpret_cast
- 3.const_cast
- 在这里插入图片描述
- 4. dynamic_cast
学习目标:
标准C++为了加强类型转换的可视性,引入了四种命名的强制类型转换操作符:
static_cast、reinterpret_cast、const_cast、dynamic_cast
1.static_cast
2. reinterpret_cast
3.const_cast
4. dynamic_cast
学习过程
类型转换是我们日常学习和写代码总会遇见的事件,在学习C语言时,我们就经常会碰到隐式类型转换,对于一些系统接口函数,我们又需要显示类型转换。 对于这些类型转换,显示的还好些,隐式类型的转换就有些麻烦,因此C++提出了自己的类型转化风格,注意因为C++要兼容C语言,所以C++中还可以使用C语言的
转化风格。
1.static_cast
static_cast用于非多态类型的转换(静态转换),编译器隐式执行的任何类型转换都可用static_cast,但它不能用于两个不相关的类型进行转换。
所谓相关就是像double、int、long int 这些类型就是互相相关类型。
不相关就是像指针,int 等类型就是互相不相关类型。
使用static_cast的场景一般是在会发生隐式类型转换的时候。
int main()
{double a = 10.12;int i = static_cast<int> (a);std::cout << i << std::endl;return 0;
}
2. reinterpret_cast
reinterpret_cast操作符通常为操作数的位模式提供较低层次的重新解释,用于将一种类型转换为另一种不同的(不相关的)类型。
int main()
{int i = 10;int* pi = reinterpret_cast<int*> (10);std::cout << pi << std::endl;return 0;
}
3.const_cast
const_cast最常用的用途就是删除变量的const属性,方便赋值。
int main()
{const int i = 20;int* p = const_cast<int*> (&i);*p = 13; //*p修改数据, i的数据是否修改了呢? std::cout << i << std::endl; return 0;
}
这里我们看到打印出来的i的值并没有随着*p的赋值变为13,这是否说明我们的i的值并没有没修改呢?
实际上这是因为编译器的优化导致的,由于i为const属性,所以编译器在打印i时,直接将早已被保存在寄存器的i的初始值10进行打印了,并没有去访问内存。 (在之前我们学习多线程也遇到过这种情况,我们是使用volatile关键字来解决的)
int main()
{//const int i = 20;volatile const int i = 20;int* p = const_cast<int*> (&i);*p = 13;std::cout << i << std::endl;return 0;
}
4. dynamic_cast
dynamic_cast用于将一个父类对象的指针/引用转换为子类对象的指针或引用(动态转换)
向上转型:子类对象指针/引用->父类指针/引用(不需要转换,赋值兼容规则)
向下转型:父类对象指针/引用->子类指针/引用(用dynamic_cast转型是安全的)
注意:
- dynamic_cast只能用于父类含有虚函数的类
- dynamic_cast会先检查是否能转换成功,能成功则转换,不能则返回0
对于向上转型,我们不需要使用dynamic_cast进行转换,因为它们由于继承的切片机制,他们在赋值上是允许的。
这里主要讨论向下转型,为什么说用dynamic_cast转型是安全的? 因为如果是向下转型,从内存来看,如果父类对象指针/引用访问到子类对象自有的成员,必然会发生越界访问的问题。 所以如果使用dynamic_cast进行转换,识别到是向下转型,就会返回0,这就避免了越界访问的风险。
class A
{
public:virtual void f() {}
};
class B : public A
{};void fun(A* pa)
{// dynamic_cast会先检查是否能转换成功,能成功则转换,不能则返回0B* pb1 = static_cast<B*>(pa);B* pb2 = dynamic_cast<B*>(pa);std::cout << "pb1:" << pb1 << std::endl;std::cout << "pb2:" << pb2 << std::endl;
}
int main()
{A a;B b;fun(&a);std::cout << std::endl;fun(&b);return 0;
}