c++类型转换与RTTI运行阶段类型识别

简介: 我们都知道C++完全兼容C语言,C语言的转换方式很简单,可以在任意类型之间转换,但这也恰恰是缺点,因为极其不安全,可能不经意间将指向const对象的指针转换成非const对象的指针,可能将基类对象指针转成了派生类对象的指针,这种转换很容易出bug,需要严格审查代码才能消除这种隐患,但是C这种转换方式不利于我们审查代码,且程序运行时也可能会出bug。

我们都知道C++完全兼容C语言,C语言的转换方式很简单,可以在任意类型之间转换,但这也恰恰是缺点,因为极其不安全,可能不经意间将指向const对象的指针转换成非const对象的指针,可能将基类对象指针转成了派生类对象的指针,这种转换很容易出bug,需要严格审查代码才能消除这种隐患,但是C这种转换方式不利于我们审查代码,且程序运行时也可能会出bug。

所以C++引入的这几种类型转换可以完美的解决上述问题,不同场景下不同需求使用不同的类型转换方式,同时有利于代码审查。

孙悟空都只有七十二变,不能瞎变,所以c++给类型转换做了限制。

1、static_cast

static_cast

仅当type_name可以被隐式转换为expression所属类型或expression可隐式转换成type_name所属类型时,上述转换才是合法的。

static_cast是用得最多的一类类型转换符,常见的枚举值转成整形,float转整形之类的,都是可以的。

另外,static_cast还可以将派生类指针转换为基类指针,而且一定条件下还能将基类指针转换为派生类指针,且不会报错,只是一些只有派生类才会有的函数、成员变量,转换过来的指针也不会有。

Test test;
    TestDerived derived;
    cout << "----------" << endl;
    Test* tp = static_cast<Test*>(&derived);
    tp->func();
    cout << "-----------------" << endl;
    TestDerived* dp = static_cast<TestDerived*>(&test);
    dp->func();
    dp->speak();
//以下是控制台输出
----------
TestDerived func
-----------------
test func

2、dynamic_cast

dynamic_cast运算符的语法和static_cast一样,但它的作用和static_cast略有区别。

kotlin中有个语法叫 is,本人觉得dynamic_cast就是kotlin中的is

dynamic_cast,一般只用于基类和派生类之间的转换,而且只能用于派生类指针转换成基类指针,不能反向转换。

if (Test* tpp = dynamic_cast<Test*>(&derived)) {
        cout << "devived can cast to test" << endl;
    }
    if (TestDerived* dpp = dynamic_cast<TestDerived*>(&test)) {
        cout << "test can cast to TestDerived" << endl;
    }
//输出
devived can cast to test

如代码所示,如果dynamic_cast转换成功,将返回一个指针,如果转换失败,将返回一个空指针。所以代码中的两个if判断,只有一个生效。看这种调用方式,是不是和kotlin中的 is 很相象呢。

3、const_cast

const_cast运算符,只用于执行一种用途的类型转换,即改变值为const或volatile。

它一般用于去const运算符。但去运算符之后的效果却是难以预料。

const int num = 10;
    const int* tempN = const_cast<const int*>(&num);
    cout << "tempn = " << *tempN << endl;
    int* temppp = const_cast<int*>(tempN);
    *temppp = 20;
    cout << "num = " << num << "  tempn = " << *tempN << "  temppp = " << *temppp << endl;
输出:
tempn = 10
num = 10  tempn = 20  temppp = 20

如上述代码所示,num是const类型的整形值,它的值始终为10,无法更改。这种转换慎用。

4、reinterpret_cast

没有啥特殊场景运用,类似于c语言中的强制转换,一般用得极少。

5、RTTI

RTTI,运行阶段类型识别的简称。

在多态中,比如上面代码中有基类Test和TestDerived,现在有一个Test指针,但不知道这个指针究竟指向的是基类还是派生类,怎么知道指针是指向的哪种对象呢?

这就是RTTI的工作,在运行时判断类型。目前c++中有3个支持RTTI的元素:

  • dynamic_cast,将一个指向基类的指针来生成一个指向派生类的指针,否则,该运算符将返回空指针
  • typeid,返回一个指针对象类型的值
  • type_info,结构存储了有关特定类型的信息

RTTI场景下,父类必须要有虚函数信息,因为RTTI信息存储在虚函数表中。

相关文章
|
3月前
|
C++
C++ 根据程序运行的时间和cpu频率来计算在另外的cpu上运行所花的时间
C++ 根据程序运行的时间和cpu频率来计算在另外的cpu上运行所花的时间
44 0
|
1月前
|
编译器 C语言 C++
C++入门4——类与对象3-1(构造函数的类型转换和友元详解)
C++入门4——类与对象3-1(构造函数的类型转换和友元详解)
19 1
|
1月前
|
存储 编译器 程序员
C++类型参数化
【10月更文挑战第1天】在 C++ 中,模板是实现类型参数化的主要工具,用于编写能处理多种数据类型的代码。模板分为函数模板和类模板。函数模板以 `template` 关键字定义,允许使用任意类型参数 `T`,并在调用时自动推导具体类型。类模板则定义泛型类,如动态数组,可在实例化时指定具体类型。模板还支持特化,为特定类型提供定制实现。模板在编译时实例化,需放置在头文件中以确保编译器可见。
32 11
|
1月前
|
存储 编译器 数据安全/隐私保护
【C++篇】C++类与对象深度解析(四):初始化列表、类型转换与static成员详解2
【C++篇】C++类与对象深度解析(四):初始化列表、类型转换与static成员详解
29 3
|
1月前
|
编译器 C++
【C++篇】C++类与对象深度解析(四):初始化列表、类型转换与static成员详解1
【C++篇】C++类与对象深度解析(四):初始化列表、类型转换与static成员详解
45 3
|
1月前
|
C++
C++入门4——类与对象3-2(构造函数的类型转换和友元详解)
C++入门4——类与对象3-2(构造函数的类型转换和友元详解)
21 0
|
3月前
|
C语言 C++
vscode——如何在vscode中运行C/C++
vscode——如何在vscode中运行C/C++
53 1
|
2月前
|
安全 程序员 C语言
C++(四)类型强转
本文详细介绍了C++中的四种类型强制转换:`static_cast`、`reinterpret_cast`、`const_cast`和`dynamic_cast`。每种转换都有其特定用途和适用场景,如`static_cast`用于相关类型间的显式转换,`reinterpret_cast`用于低层内存布局操作,`const_cast`用于添加或移除`const`限定符,而`dynamic_cast`则用于运行时的类型检查和转换。通过具体示例展示了如何正确使用这四种转换操作符,帮助开发者更好地理解和掌握C++中的类型转换机制。
|
3月前
|
C++
使用 QML 类型系统注册 C++ 类型
使用 QML 类型系统注册 C++ 类型
56 0
|
4月前
|
编译器 C++ 运维
开发与运维函数问题之函数的返回类型如何解决
开发与运维函数问题之函数的返回类型如何解决
38 6