类型转换(cast)是将一种数据类型转换成另一种数据类型。例如,如果将一个整型值赋给一个浮点类型的变量,编译器会暗地里将其转换成浮点类型。

  转换是非常有用的,但是它也会带来一些问题,比如在转换指针时,我们很可能将其转换成一个比它更大的类型,但这可能会破坏其他的数据。

  应该小心类型转换,因为转换也就相当于对编译器说:忘记类型检查,把它看做其他的类型。

  一般情况下,尽量少的去使用类型转换,除非用来解决非常特殊的问题。

无论什么原因,任何一个程序如果使用很多类型转换都值得怀疑。

  标准c++提供了一个显示的转换的语法,来替代旧的C风格的类型转换。

  使用C风格的强制转换可以把想要的任何东西转换成我们需要的类型。那为什么还需要一个新的C++类型的强制转换呢?

  新类型的强制转换可以提供更好的控制强制转换过程,允许控制各种不同种类的强制转换。C++风格的强制转换其他的好处是,它们能更清晰的表明它们要干什么。程序员只要扫一眼这样的代码,就能立即知道一个强制转换的目的。

//2023年3月10日19:52:46
#pragma warning(disable:4996)
#define _CRT_SECURE_NO_WARNINGS 1 #include <iostream>
#include <string>
using namespace std; //静态转换
//1.基础类型转换
void test01()
{
char a = 'a';
//char->double;
//static_cast<目标类型>(待转类型)
double d = static_cast<double>(a); //double d1 = (double)a;
}
//2.有层次关系的类的指针或引用转换
class Father
{ };
class Son :public Father
{ }; class Other
{ };
void test02()
{
Father* f = NULL;
Son* s = NULL; //向下转换,不安全
static_cast<Son*>(f);
//向上转换,安全
Father* f1 = static_cast<Father*>(s);
//没有继承关系的类之间的指针不能转换
//Other* o = static_cast<Other*>(s);
} //引用转换
void test03()
{
Father f;
Son s; Father& ref_f = f;
Son& ref_s = s; //向上转换,安全
static_cast<Father&>(ref_s); //向下转换,不安全
static_cast<Son&>(ref_f);
} //动态转换
void test04()
{
//char a = 'a';
//dynamic_cast<double>(a);//基础数据类型不能使用动态转换 Father* f = NULL;
Son* s = NULL;
//向上,安全
Father* f1 = dynamic_cast<Father*>(s);
//向下,不安全,会检查
//Son* s1 = dynamic_cast<Son *>(f);
} class Father2
{
public:
virtual void func() {};
};
class Son2 :public Father2
{
public:
virtual void func() {};
}; //发生多态时,向下转换,动态转换就可以
void test05()
{
Father2* f = new Son2; dynamic_cast<Son2*>(f);
} //常量转换
void test06()
{
const int* p = NULL;
//const-->不带const
int* newP = const_cast<int*>(p); int* pp = NULL;
const int* newPP = const_cast<const int*>(pp);
}
//重新解释转换
void test07()
{
int a = 10;
int* p = reinterpret_cast<int*>(a); Father* f = NULL;
Other* o = reinterpret_cast<Other*>(f);
}
int main()
{
test05();
system("pause");
return EXIT_SUCCESS;
}

1.静态转换(static_cast)

●用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换。

▷进行上行转换(把派生类的指针或引用转换成基类表示)是安全的;

▷进行下行转换(把基类指针或引用转换成派生类表示)时,由于没有动态类型检查,所以是不安全的。

●用于基本数据类型之间的转换,如把int转换成char,把char转换成int。这种转换的安全性也要开发人员来保证。

class Animal{};
class Dog : public Animal{};
class Other{}; //基础数据类型转换
void test01(){
char a = 'a';
double b = static_cast<double>(a);
} //继承关系指针互相转换
void test02(){
//继承关系指针转换
Animal* animal01 = NULL;
Dog* dog01 = NULL;
//子类指针转成父类指针,安全
Animal* animal02 = static_cast<Animal*>(dog01);
//父类指针转成子类指针,不安全
Dog* dog02 = static_cast<Dog*>(animal01);
} //继承关系引用相互转换
void test03(){ Animal ani_ref;
Dog dog_ref;
//继承关系指针转换
Animal& animal01 = ani_ref;
Dog& dog01 = dog_ref;
//子类指针转成父类指针,安全
Animal& animal02 = static_cast<Animal&>(dog01);
//父类指针转成子类指针,不安全
Dog& dog02 = static_cast<Dog&>(animal01);
} //无继承关系指针转换
void test04(){ Animal* animal01 = NULL;
Other* other01 = NULL; //转换失败
//Animal* animal02 = static_cast<Animal*>(other01);
}

2.动态转换(dynamic_cast)

●dynamic_cast主要用于类层次间的上行转换和下行转换;

●在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的;

●在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全;

class Animal {
public:
virtual void ShowName() = 0;
};
class Dog : public Animal{
virtual void ShowName(){
cout << "I am a dog!" << endl;
}
};
class Other {
public:
void PrintSomething(){
cout << "我是其他类!" << endl;
}
}; //普通类型转换
void test01(){ //不支持基础数据类型
int a = 10;
//double a = dynamic_cast<double>(a);
} //继承关系指针
void test02(){ Animal* animal01 = NULL;
Dog* dog01 = new Dog; //子类指针转换成父类指针 可以
Animal* animal02 = dynamic_cast<Animal*>(dog01);
animal02->ShowName();
//父类指针转换成子类指针 不可以
//Dog* dog02 = dynamic_cast<Dog*>(animal01);
} //继承关系引用
void test03(){ Dog dog_ref;
Dog& dog01 = dog_ref; //子类引用转换成父类引用 可以
Animal& animal02 = dynamic_cast<Animal&>(dog01);
animal02.ShowName();
} //无继承关系指针转换
void test04(){ Animal* animal01 = NULL;
Other* other = NULL; //不可以
//Animal* animal02 = dynamic_cast<Animal*>(other);
}

3.常量转换(const_cast)

该运算符用来修改类型的const属性。。

●常量指针被转化成非常量指针,并且仍然指向原来的对象;

●常量引用被转换成非常量引用,并且仍然指向原来的对象;

 注意:不能直接对非指针和非引用的变量使用const_cast操作符去直接移除它的const。
//常量指针转换成非常量指针
void test01(){ const int* p = NULL;
int* np = const_cast<int*>(p); int* pp = NULL;
const int* npp = const_cast<const int*>(pp); const int a = 10; //不能对非指针或非引用进行转换
//int b = const_cast<int>(a); } //常量引用转换成非常量引用
void test02(){ int num = 10;
int & refNum = num; const int& refNum2 = const_cast<const int&>(refNum); }

4.重新解释转换(reinterpret_cast)

  这是最不安全的一种转换机制,最有可能出问题。

  主要用于将一种数据类型从一种类型转换为另一种类型。它可以将一个指针转换成一个整数,也可以将一个整数转换成一个指针.

63.C++类型转换的更多相关文章

  1. 密码学笔记-一段base64wp

    CTF--练习平台 例题: 一段Base64 flag格式:flag{xxxxxxxxxxxxx} 附件: base64.txt 1.base64解码:http://base64.xpcha.com/ ...

  2. c++ 数据类型转换: static_cast dynamic_cast reinterpret_cast const_cast

    c++ 数据类型转换: static_cast dynamic_cast reinterpret_cast const_cast  [版权声明]转载请注明出处 http://www.cnblogs.c ...

  3. system verilog中的类型转换(type casting)、位宽转换(size casting)和符号转换(sign casting)

    类型转换 verilog中,任何类型的任何数值都用来给任何类型赋值.verilog使用赋值语句自动将一种类型的数值转换为另一种类型. 例如,当一个wire类型赋值给一个reg类型的变量时,wire类型 ...

  4. C++库研究笔记——操作符重载实现类型转换&这样做的意义

    目标: 已知这个接口: std::vector<double> add_vec(double *d1, double *d2) { ..... return result; } 我们自定义 ...

  5. java注释 命名 数据类型 基本类型转换 位运算符 逻辑运算符 三目运算符

    一.java注释 1.单行注释  //注释内容 2.多行注释 /*注释内容*/ 3.文档注释(可用javadoc工具生成api文档,不过我还没试过)/**文档注释*/,文档注释可以在使用的时候看见注释 ...

  6. 从字节码看java类型转换【 深入理解 (T[]) new Object[size] 】

    我们都知道,java中对类型的检查是很严格的,所以我们平操作时,也往往很小心. 如题: (T[]) new Object[size],这种写法是一般我们是不会干的!但是有点经验的同学,还是会遇到这样写 ...

  7. Java基本数据类型总结、类型转换、常量的声明规范,final关键字的用法

    1  Java 基本数据类型 变量就是申请内存来存储值.也就是说,当创建变量的时候,需要在内存中申请空间. 内存管理系统根据变量的类型为变量分配存储空间,分配的空间只能用来储存该类型数据. 因此,通过 ...

  8. Python基本语法_强制数据类型转换

    目录 目录 前言 软件环境 Python数据类型的显式转换 显式转换的多种类型 Non-String转换为String str函数 repr str和repr的区别 eval Non-int转换为in ...

  9. 类型转换运算符、*运算符重载、->运算符重载、operator new 和 operator delete

    一.类型转换运算符 必须是成员函数,不能是友元函数 没有参数 不能指定返回类型 函数原型:operator 类型名();  C++ Code  1 2 3 4 5 6 7 8 9 10 11 12 1 ...

  10. C++之强制类型转换

     C++ Code  12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849 ...

随机推荐

  1. js-3part-Javascript使用Ajax

    getElementsByName使用方法如下是input标签,我们尝试从里面获取到csrf的value值. 这个csrf标签,是隐藏的,在浏览器页面element可以看到,在html源码里面,是看不 ...

  2. 删除Windows10资源管理器多余的入口

    ///// 删除3D对象 定位到HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\Nam ...

  3. WEB攻击与防御技术 pikachu——文件包含下载上传漏洞

    文件包含漏洞 一.LOCAL 上来就是一个选择,当我们选择一个球员的时候,如图所示,url会提交一个get请求 如果这个服务器架设在linux上我们就可以一直../../../../../到根目录然后 ...

  4. Jmeter添加BeanShell后置处理程序保存响应结果

    对于某些请求,无法通过保存响应到文件这个组件来进行保存(会出现UNKNOW文件类型). 那么就可以通过BeanShell后置处理程序来进行将响应结果直接输出到文件,并可以直接指定文件名和后缀. imp ...

  5. IOS弹出系统键盘后,页面不恢复

    <script> var u = navigator.userAgent, app = navigator.appVersion var isIOS = !!u.match(/\(i[^; ...

  6. Mysql存储类型长度

    分析MySQL数据类型的长度 MySQL有几种数据类型可以限制类型的"长度",有CHAR(Length).VARCHAR(Length).TINYINT(Length).SMALL ...

  7. sourceCRT 开发vbs测试

    $language = "VBScript" $interface = "1.0" ' This automatically generated script ...

  8. 树莓派启动后自动发送本地IP 到指定邮箱

    在 /etc/init.d   目录下建立 GetLocalip.py 文件 #coding: utf-8 import smtplib from email.mime.text import MIM ...

  9. Spring5框架

    Spring5框架 一.Spring框架概述 1.1 Spring框架简介 Spring是一个开源框架,它由Rod Johnson创建.它是为了解决企业应用开发的复杂性而创建的.Spring使用基本的 ...

  10. MySql 自动设置时间(自动获取时间,填充时间)

    应用场景: 1.在数据表中,要记录每条数据是什么时候创建的,不需要应用程序去特意记录,而由数据数据库获取当前时间自动记录创建时间: 2.在数据库中,要记录每条数据是什么时候修改的,不需要应用程序去特意 ...