首页 > 编程语言 >c++类型转换

c++类型转换

时间:2024-05-26 21:34:16浏览次数:18  
标签:类型转换 转换 int c++ cast 类型 指针

强类型语言

强类型语言也称为强类型定义语言,是一种总是强制类型定义的语言。它的主要特点包括:

  1. 强制类型定义:强类型语言要求变量在使用之前必须明确声明其类型,并且限制了不同类型之间的隐式转换。这意味着所有变量都必须先定义后使用,并且变量的类型在编译时就被严格检查。
  2. 编译时类型检查:强类型语言在编译时进行严格的类型检查,能够在程序运行之前捕捉到潜在的类型错误。这种类型检查能够防止一些常见的编程错误,如类型转换错误和未定义的行为,从而提高代码的健壮性和可靠性。
  3. 更好的代码可读性和可维护性:由于强类型语言要求显式声明变量的类型,使得代码更易读、更易理解。类型信息的清晰性和一致性有助于他人理解和维护代码。
  4. 更高的类型安全性:通过强制变量和操作符的类型匹配,强类型语言提高了程序的类型安全性。
  5. 更好的性能优化和静态分析:强类型语言在编译时能够进行更多的性能优化和静态分析,从而可能提高程序的运行效率。

常见的强类型语言包括Java、C/C++、.NET等。

RTTI

RTTI(Run-Time Type Identification,运行时类型识别)是C++中的一个特性,它允许程序在运行时查询对象的确切类型。这主要通过dynamic_cast操作符和typeid操作符来实现。

c语言的类型转换

在C语言中,如果赋值运算符左右两侧类型不同,或者形参与实参类型不匹配,或者返回值类型与接收返回值类型不一致时,就需要发生类型转化,C语言中总共有两种形式的类型转换:隐式类型转换和显式类型转换。

void f()
{
    int a = 1;
    double d = a; //隐式类型转化
    int* p  = &a;
    int  address = (int)p; //显示类型转换
}

c语言类型转换的缺陷

  1. 数据丢失:当将一个较大数据类型的值转换为较小数据类型时,可能会丢失高位的数据。例如,将一个long类型的值转换为int类型,如果long类型的值超出了int类型的表示范围,就会发生数据截断。
  2. 指针类型转换:指针类型转换特别危险,因为它们允许程序员访问不同类型的内存区域。如果转换后的指针被错误地解引用,可能会导致未定义的行为,包括程序崩溃、数据损坏或安全漏洞。
  3. 类型不匹配:在函数参数传递和返回值时,如果类型不匹配且没有进行适当的类型转换,可能会导致错误的结果或程序崩溃。

C++类型转换

static_cast

static_cast用于非多态类型的转换(静态转换),编译器隐式执行的任何类型转换都可用static_cast,但它不能用于两个不相关的类型进行转换。

1.static_cast可以用于基础数据类型(如整型、浮点型、字符型等)之间的转换

int a = 1;
double b = static_cast<double>(a); //将int转换为double

2.在类层次结构中,static_cast可以用于向上转型(即派生类到基类的转换),但不能用来向下转型,因为这会带来不安全性。向下转型应该使用dynamic_cast(如果基类包含虚函数)或reinterpret_cast(如果基类不包含虚函数但你确定转换是安全的)。

class Base {};
class Derived : public Base {};
Derived* d = new Derived();
Base* b = static_cast<Base*> (d); //向上转型

3.void指针和有类型指针之间的转换

int x = 1;
int* p = &x;
void * p1 = static_cast<void*>(p);
int *  p2 = static_cast<int*>(p1);

static_cast在编译时进行检查,确保转换是合法的。如果转换不合法,编译器会报错。

reinterpret_cast

提供了最低级别的转换,允许你将任何指针类型转换为任何其他指针类型,以及将整数类型转换为指针或将指针转换为整数。这种转换非常强大,但也很危险,因为它几乎不进行任何类型检查,仅仅是对二进制表示的重新解释。

当使用 reinterpret_cast进行类型转换时,实际上是在告诉编译器:请把这个类型的内存表示当作另一个类型来解读。

比如将一个 int* 转换为 char* 时,实际上是在告诉编译器把这个指向整数的指针当作指向字符的指针来用。编译器会照做,但它不会改变内存中实际的数据,只是改变了对这些数据的解释方式。

int x= 1;
int* p = &x;
char* c_p = reinterpret_cast<char*>(p); //将int*转换为char* 
void* p1 = reinterpret_cast<void*>(x); // 将整数值转换为指针  

const_cast

主要用于去除指针或引用类型的常量性。换句话说,它允许我们修改一个原本被定义为常量的对象。

注意:

  • 类型安全:虽然const_cast允许我们修改常量对象,但这并不意味着我们应该滥用它。修改常量对象可能会导致不可预见的后果,包括程序崩溃、数据损坏等。因此,在使用const_cast时,我们应该非常小心,并确保我们真的需要修改这个对象。
  • 编译器优化:编译器可能会对常量进行优化,因为它们知道这些值在程序的剩余部分中不会改变。如果我们使用const_cast来修改一个常量,并且编译器已经基于该常量的原始值进行了优化,那么修改可能不会反映在最终的程序行为中。
  • 指针和引用:const_cast只能用于指针和引用类型。对于非指针/引用类型的常量,我们不能使用const_cast来修改它们。
const int a = 1;
int* p = const_cast<int*>(&a); //去掉a的const属性
const int& b = a;
int& c = const_cast<int&>(b); //去掉b的const属性

dynamic_cast

主要用于在类的继承层次结构中进行安全的向下转型(downcasting)。它主要处理基类指针或引用到派生类指针或引用的转换。

为什么要使用dynamic_cast?

在C++中,当我们有一个基类指针或引用,并且我们想要将其转换为派生类指针或引用时,我们需要一种机制来确保这种转换是安全的。

注意:

  • 只有在支持RTTI(运行时类型识别)的编译环境中,dynamic_cast才能正常工作。RTTI通常是通过编译器选项开启的,例如使用g++的-frtti选项。
  • dynamic_cast主要用于指针或引用类型的转换。被转换的类(即基类)必须至少有一个虚函数(即使是虚析构函数)。这是因为dynamic_cast依赖于虚函数表来实现其类型检查功能。

语法:

//target_type 是你想要转换到的目标类型(通常是派生类类型)
//expression 是要进行转换的源表达式(通常是基类指针或引用)
targert_type target = dynamic_cast<targert_type>(expression);

如果转换成功,target将被赋予转换后的值;如果转换失败(即源指针或引用不指向目标类型的对象),则target将被赋予空指针(对于指针类型)或抛出std::bad_cast异常(对于引用类型,但通常不推荐使用dynamic_cast进行引用类型的转换,因为异常在这种情况下是无法捕获的)。

class Base() 
{
public:
    virtual void fun() {};
};
class Derived : public Base {};
int main()
{
    Base* b_p = new Derived();
    Derived* d_p = dynamic_cast<Derived*>(b_p); //可以
    Base* b_p1 = new Base();
    Derived* d_p1 = dynamic_cast<Derived*>(b_p); //不可以
}

标签:类型转换,转换,int,c++,cast,类型,指针
From: https://blog.csdn.net/weixin_53425006/article/details/139115040

相关文章

  • 算法刷题笔记 前缀和(C++实现)
    文章目录题目描述基本思路实现代码题目描述输入一个长度为n的整数序列。接下来再输入m个询问,每个询问输入一对l,r。对于每个询问,输出原序列中从第l个数到第r个数的和。输入格式第一行包含两个整数n和m。第二行包含n个整数,表示整数数列。接下来m行,每行包含两个整数......
  • 算法刷题笔记 数的范围(C++实现)(二分法重要例题)
    文章目录题目描述题目思路题目代码(C++)题目感想题目描述给定一个按照升序排列的长度为n的整数数组,以及q个查询。对于每个查询,返回一个元素k的起始位置和终止位置(位置从0开始计数)。如果数组中不存在该元素,则返回-1-1。输入格式:第一行包含整数n和q,表示数组长度和询......
  • 【C++风云录】走进数字农业:农业科学与粮食安全
    跨越边界:农业模拟库的编程特性与应用领域前言在本篇文章中,我们将深入探讨六个领域的软件库—APSIM,AgroLib,CropModelMKS,SoilR,Bionet和FSEarth。这些库均用于农业生态系统建模、作物模拟、农业数据处理和分析、合成作物模型构造、土壤碳氮循环模型集成、生物网络模拟以及农......
  • 【C++】牛客 ——DP36 abb
    ✨题目链接:DP36abb✨题目描述 leafee最近爱上了abb型语句,比如“叠词词”、“恶心心”leafee拿到了一个只含有小写字母的字符串,她想知道有多少个"abb"型的子序列?定义:abb型字符串满足以下条件:字符串长度为3。字符串后两位相同。字符串前两位不同。✨输入......
  • 2024年华为OD机试真题-计算面积-C++-OD统一考试(D卷)
     2024年OD统一考试(D卷)完整题库:华为OD机试2024年最新题库(Python、JAVA、C++合集)题目描述:绘图机器的绘图笔初始位置在原点(0,0),机器启动后其绘图笔按下面规则绘制直线:1)尝试沿着横向坐标轴正向绘制直线,直到给定的终点值E。2)期间可通过指令在纵坐标轴方向进行偏移,并同时绘制直......
  • 线程池(C++)
    个人主页:Lei宝啊 愿所有美好如期而遇线程池实现线程类#pragmaonce#include<pthread.h>#include<iostream>#include<vector>#include<string>#include<cstdlib>#include<cstring>#include<functional>#include<unistd.h>#in......
  • C++——list的实现以及源码
    前言:最近学习了c++list的实现,这让我对迭代器的理解又上升了一个新的高度,注意:代码里的list是放在一个叫zgw的命名空间里边,但是在实现list的代码中没有加namespace,这里给个注意,以后复习时能看懂。list的节点:我们首先需要搞出一个list的节点,来存储数据,以及节点的下一个指针,和节......
  • C和C++内存管理
    C和C++的内存管理C/C++中程序内存区域的划分C语言中动态内存管理方式C++中动态内存管理方式new和delete操作内置类型new和delete操作自定义类型operratornew函数和operatordelete函数new和delete的实现原理内置类型自定义类型new的原理delete的原理newT[N]的原理dele......
  • CCF-GESP 等级考试 2024年3月认证C++一级真题解析
    2024年03月真题1单选题第1题C++表达式(3-2)*3+5的值是()。A.-13B.8C.2D.0正确答案:B.8解析:首先计算括号中的表达式(3-2),得到(1)。接下来进行乘法运算(1*3),得到(3)。最后进行加法运算(3+5),得到(8)。因此,表达式的值是(8)。第2题C++......
  • CCF-GESP 等级考试 2024年3月认证C++一级真题
    2024年03月真题1单选题第1题C++表达式(3-2)*3+5的值是()。A.-13B.8C.2D.0第2题C++语句cout<<"5%2="<<5%2执行后的输出是()。A.22B.11C.5%2=2D.5%2=1第3题执行C++语句cin>>a时如果输入5+2,下述说法正确的是()。A.变量a将被......