写点什么

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

作者:向阳逐梦
  • 2023-07-15
    四川
  • 本文字数:1516 字

    阅读完需:约 5 分钟

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

我们都知道 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 = 10num = 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 信息存储在虚函数表中。


发布于: 刚刚阅读数: 6
用户头像

向阳逐梦

关注

人生享受编程,编程造就人生! 2022-06-01 加入

某公司芯片测试工程师,嵌入式开发工程师,InfoQ签约作者,阿里云星级博主,华为云·云享专家。座右铭:向着太阳,追逐梦想!

评论

发布
暂无评论
c++类型转换与RTTI运行阶段类型识别_向阳逐梦_InfoQ写作社区