类型转换(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. 错题记录:C51同一个hex文件偶尔效果不行 的处理方法

    51单片机很多方面和C语言有区别,经验下来,总结以下:1.关于变量报错:报错的原因大多是因为编译器C++版本不同,所以变量我都推荐使用驼峰命名法;2.如果同一个hex文件,或者改的代码自己认为没问题 ...

  2. RGB以及文档流

    继承 继承 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF ...

  3. flume往kafka中导入数据

    1.编辑flume的配置文件 a1.sources = r1 a1.channels = c1 # Describe/configure the source a1.sources.r1.type = ...

  4. 2022-07-11 第一小组 张明旭 前端JS学习记录

    今天是正式学习的第三天,每天一大部分前端的新知识,吐瘦两斤,听课晕乎乎的.不过小事,靠笔记和视频苟活 知识点: JavaScript是什么? 编程语言.脚本语言.依赖于某种容器(浏览器)运行 有浏览器 ...

  5. 【逆向】Magniber 勒索软件样本分析

    .wiz-editor-body .wiz-code-container { position: relative; padding: 8px 0; margin: 5px 0; text-inden ...

  6. 01背包&完全背包二维写法的对比,进而理解一维优化后的正逆序

    01背包题解 完全背包题解 二维写法时两种背包问题核心代码的区别: 可以看出,01背包用的是上一层的数据,完全背包用的是当前层的数据 所以优化为一维时, 01背包需逆序 for (int i = 1; ...

  7. Springboot中@Autowired为何获取了我们没有注入的Bean?

    Springboot中@Autowired为何获取了我们没有注入的Bean? 在做仿牛客网项目的时候,有这样一段话: @Autowired private TemplateEngine templat ...

  8. CSS 常用样式-盒子实体化三属性

    如果想在浏览器中具体看到一个盒子占有的实际位置,需要设置盒子可以实体化的三属性. 实体化属性:

  9. eclipse project is missing required java project

    eclipse project is missing required java project eclipse版本: 2022-03 这情况就是maven包出了问题 具体的说不上 看我的解决方法: ...

  10. lisp入门资料收集

    1.一些文档 http://acl.readthedocs.io/en/latest/zhCN/index.html http://daiyuwen.freeshell.org/gb/lisp.htm ...