c++类型转换

强类型语言

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

  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); //不可以
}
  • 26
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值