C++类型转化关键字

2023-12-13 15:40:52

1.C 语言类型转化

void Test ()
{
    //隐式类型转换
    int i = 1;
    double d = i;
    printf("%d, %f\n", i, d);

    //显式强制转换
    int* ptr = &i;
    int value = (int) p;
    printf("%x, %d\n" , ptr, value);
}

2.C++的类型转化

C 语言的转换格式过于精简,有不少缺点的:

  1. 数据精度丢失
  2. 显式类型转换将所有情况混合在一起,代码不清晰

因此 C++ 提出了类型转化风格,但因为 C++ 要兼容 C 语言,所以 C++ 中还可以使用 C 语言的转化风格,导致这一风格变成值得遵循的非硬性规则。

2.1.static_cast

编译器隐式执行的任何类型转换都可以使用 static_cast,但它不能用于两个不相关的类型进行转换,这会引发编译器报错。

#include <iostream>
using namespace std;
int main()
{
	double d = 12.34;
	int a = static_cast<int>(d);//转化成功
	cout << a << endl;

	//int* p = static_cast<int*>(a);//转化失败
	
	return 0;
}

2.2.reinterpret_cast

强制类型转化可以使用 reinterpret_cast 表明。

#include <iostream>
using namespace std;
int main()
{
	double d = 12.34;
	int a = static_cast<int>(d);//转化成功
	cout << a << endl;

	//int* p = static_cast<int*>(a);//转化失败
	int* p = reinterpret_cast<int*>(a);//转化成功
	cout << p << endl;
	
	return 0;
}

2.3.const_cast

const_cast 最常用的用途就是删除变量的 const 属性,方便赋值,但是您需要注意一些“奇怪”的现象,免得坑到自己。

#include <iostream>
using namespace std;

void Test()
{
	const int a = 10;
	int* pa = const_cast<int*>(&a);
	*pa = 3;
	cout << a << endl;//由于 a 是一个常量,因此就会导致这里提前被替换为 10,还来不及被指针修改
	cout << *pa << endl;
}

int main()
{
	Test();
	return 0;
}

2.4.dynamic_cast

可以将一个父类对象的“指针/引用”转换为子类对象的“指针/引用”(动态转换),避免危险的行为。

#include <iostream>
using namespace std;

class Father
{
public:
	virtual void f() {}
};

class Son : public Father
{};

void fun(Father* pf)
{
	//dynamic_cast 会先检查是否能转化成功,能成功转化,不能则返回 nullptr
	//如果 pf 得到的是子类指针还好,但如果真的就是父类指针本身,转化为子类后就有可能会造成越界问题
	Son* pb1 = static_cast<Son*>(pf);
	Son* pb2 = dynamic_cast<Son*>(pf);
	cout << "pb1:" << pb1 << " pb2:" << pb2 << endl;
}
int main()
{
	Father f;
	Son s;

	fun(&f);
	fun(&s);

	return 0;
}

3.RTT机制

RTTIRun-time Type identification 的简称,翻译为“运行时类型识别”。用于在运行时获取对象的实际类型信息,它允许程序在运行时判断对象的实际类型,以便进行相应的操作。而 C++ 主要通过以下方式来支持 RTTI

  1. typeid 运算符,用于获取变量或表达式的类型信息,但它并不能直接得到类型对应的字符串。typeid 返回的是 std::type_info 类型的对象,代表被查询对象的类型信息。要将类型信息转换为字符串,通常需要使用 type_info::name() 方法

    #include <iostream>
    #include <typeinfo>
    using namespace std;
    
    class Base
    {
        //...
    };
    
    class Derived : public Base
    {
        //...
    };
    
    int main()
    {
        Base* ptr1 = new Derived();
        Derived* ptr2 = new Derived();
    
        if (typeid(*ptr1) == typeid(Derived))
        {
            cout << "YES" << endl;
        }
        if (typeid(*ptr2) == typeid(Derived))
        {
            cout << "YES" << endl;
        }
    
        cout << typeid(ptr1).name() << endl;
    
        delete ptr1;
        delete ptr2;
        return 0;
    }
    
  2. dynamic_cast 运算符,上面有介绍,这里不多说

  3. decltype() 类型推导,auto 只能在声明的时候简化声明长度,而这个工具可以由用户放置任意表达式来推断表达式的类型,灵活定义变量的类型

    #include <iostream>
    #include <typeinfo>
    using namespace std;
    
    // 定义一个函数 func,返回类型为 int
    int func()
    {
        return 42;
    }
    
    int main()
    {
        //使用 decltype 推导出变量 a 的类型
        //a 的类型为 int,与 func() 的返回类型相同
        decltype(func()) a = 10;
    
        cout << typeid(a).name() << endl;
        return 0;
    }
    

文章来源:https://blog.csdn.net/m0_73168361/article/details/134898308
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。