返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C++超详细讲解强制类型转换的用法
  • 798
分享到

C++超详细讲解强制类型转换的用法

2024-04-02 19:04:59 798人浏览 独家记忆
摘要

目录static_castdynamic_castconst_castreinterpret_caststatic_cast static_cast<type-id>(e

static_cast

static_cast<type-id>(expression)

expression 转换为 type-id 类型。static_cast 是静态类型转换,发生在编译期。这种转换不会进行运行时的动态检查(RTTI),因而这种转换可能是不安全的。static_cast 典型应用场景如下:

1. 类的层级结构中,基类和子类之间指针或者引用的转换。

上行转换(Upcasting),也即子类像基类方向转换,是安全的。

下行转换(Downcasting),也即基类向子类方向转换,是不安全的,需要程序员自行保证安全转换。

下面举例说明:

class A {
public:
  virtual void func() {
    std::cout << "A::func()" << std::endl;
  } 
};
class B : public A {
public:
  virtual void func() {
    std::cout << "B::func()" << std::endl;
  }
  void print() {
    std::cout << "B::print()" << std::endl;
  }
};

对于上行转换,肯定是安全的。

  B* pb = new B();
  A* pa = static_cast<A*>(pa);
  pa->func();

对于下行转换:

  A* pa = new B();
  B* pb = static_cast<B*>(pa);
  pb->print();

这里,A* pa = new B();,由于 c++ 的多态的支持,可以使用基类指针指向子类。这里的转换是安全的,因为 pa 初始化就指向的就是 B。而下面的转换则是不安全的:

  A* pa = new A();
  B* pb = static_cast<B*>(pa);
  pb->print();

此外,对于两个不存在继承关系的两个类之间转换,总是失败的,编译器报错:

#include <iOStream>
class A {
    virtual void func(){}
};
class B {
    virtual void func(){}
};
int main(){
    A* pa = new A();
    B* pb = static_cast<B*>(pa); 
    return 0;
}

2. 基本数据类型间的转换。这种转换也是不安全的,需要程序员自行保证安全转换。 例如 intshort,直接高位截断;而 shortint 则高位根据符号位填充。两种不同类型指针间相互转换是相当危险的,例如 int*float*。将 int 转换为指针类型也是危险的转换,例如 float* p = static_cast<float*>(0X2edf);

3. 将 void 类型转换为其他类型的指针。 显然这种转换也是不安全的,需要程序员自行保证安全转换。

4. 把其他类型转换为 void 类型。

有转换构造函数或者类型转换函数的类与其它类型之间的转换。例如:

#include <iostream>
class Point{
public:
    Point(double x, double y): m_x(x), m_y(y){ }
    Point(double& x): m_x(x), m_y(1.1){ }
public:
    operator double() const { return m_x; }  //类型转换函数
    void print() {
        std::cout << "m_x: " << m_x << "  m_y: " << m_y << std::endl;
    }
private:
    double m_x;
    double m_y;
};
int main() {
    Point p1(12.5, 23.8);
    double x= static_cast<double>(p1);
    // std::cout << x << std::endl;
    Point p2 = static_cast<Point>(x);
    // p2.print();
    return 0;
}

dynamic_cast

dynamic_cast<type-id>(expression)

expression 转换为 type-id 类型,type-id 必须是类的指针、类的引用或者是 void *;如果 type-id 是指针类型,那么 expression 也必须是一个指针;如果 type-id 是一个引用,那么 expression 也必须是一个引用。

dynamic_cast 提供了运行时的检查。对于指针类型,在运行时会检查 expression 是否真正的指向一个 type-id 类型的对象,如果是,则能进行正确的转换;否则返回 nullptr。对于引用类型,若是无效转换,则在运行时会抛出异常 std::bad_cast

T1 obj;
T2* pObj = dynamic_cast<T2*>(&obj);    // 无效转换返回 nullptr
T2& refObj = dynamic_cast<T2&>(obj);   // 无效转换抛出 bad_cast 异常

上行转换:其实和 static_cast 是一样的,一般肯定能成功。例如前面用到的例子:

// A->B
B* pb = new B();
A* pa = static_cast<A*>(pa);  

但是,下面这种继承关系会转换失败:

#include <iostream>

class A {
    virtual void func(){}
};
class B : public A {
    void func(){}
};
class C : public A {
    void func(){}
};
class D : public B, public C {
    void func(){}
};
int main(){
    D* pd = new D();
    A* pa = dynamic_cast<A*>(pd);
    return 0;
}

上面这个例子,虽然也是上行转换,但是存在两条路径,在 B 和 C 都继承于 A,并且有虚函数实现,上行转换不知道从哪条路径进行转换。下面的写法则没问题:

  D* pd = new D();
  B* pb = dynamic_cast<B*>(pd);
  A* pa = dynamic_cast<A*>(pb);

下行转换:看个例子。

#include <iostream>
class A {
    virtual void func(){}
};
class B : public A {
    void func(){}
};
int main(){
    A* pa1 = new B();
    A* pa2 = new A();
    B *pb1 = dynamic_cast<B*>(pa1); // ok
    B *pb2 = dynamic_cast<B*>(pa2); // pb2 is a nullptr!
    return 0;
}

其实 dynamic_cast 本质只支持上行转换,只会沿着继承链向上遍历,找到目标类型则转换成功,否则失败。dynamic_cast 看似支持下行转换,这都是多态的缘故。上面的例子,pa1 虽然类型是 A,但实际指向 B,沿着 B 向上可以找到 B,因为第一个转换可以成功。而 pa2 指向 A,沿着 A 向上找不到 B 类型,因而转换失败。

因而在有继承关系的类的转换时候, static_cast 转换总是成功的, dynamic_cast 显然比 static_cast 更加安全。

const_cast

const_cast 用来去掉表达式的 const 修饰或 volatile 修饰,也就是将 constvolatile 类型转换为非 const 或 非 volatile 类型。

#include <iostream>
int main(){
    const int n = 111;
    int *p = const_cast<int*>(&n);
    *p = 222;
    std::cout<< "n = " << n << std::endl;
    std::cout<< "*p = " << *p << std::endl;
    return 0;
}

这里需要注意:按照正常理解,n 的打印值应该是 222。但是,由于编译器的常量传播优化std::cout<< "n = " << n << std::endl; 会被编译器替换成类似 std::cout<< "n = " << 111 << std::endl; 的语义。

reinterpret_cast

reinterpret_cast 转换直接对二进制位按照目标类型重新解释,非常粗暴,所以风险很高,慎重使用。

#include <iostream>
int main(){
    char str[]="hello world!";
    float *p = reinterpret_cast<float*>(str);
    std::cout << *p << std::endl;  // 1.14314e+27
    return 0;
}

到此这篇关于C++超详细讲解强制类型转换的用法的文章就介绍到这了,更多相关C++强制类型转换内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: C++超详细讲解强制类型转换的用法

本文链接: https://lsjlt.com/news/151940.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • C++超详细讲解强制类型转换
    目录1 C 强制类型转换2 C++ 强制类型转转1 C 强制类型转换 C 方式的强制类型转换的用法如下代码所示: (Type)(Expression) Type:需要转换成的类型Ex...
    99+
    2024-04-02
  • C++超详细讲解强制类型转换的用法
    目录static_castdynamic_castconst_castreinterpret_caststatic_cast static_cast<type-id>(e...
    99+
    2024-04-02
  • C++ 强制类型转换详解
    目录一、C强制转换二、C++强制转换1、static_cast 静态转换(编译时检查)2、const_cast 常量转换3、reinterpret_cast 重新解释转换4、dyna...
    99+
    2024-04-02
  • C++强制类型转换的方法
    今天小编给大家分享一下C++强制类型转换的方法的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。1 C 强制类型转换C 方式的强...
    99+
    2023-06-30
  • C++中的强制类型转换操作详解
    目录相关术语C语言中的强制类型转换C++中的强制类型转换static_castdynamic_castreinterpret_castconst_cast注意事项相关术语 强制类型转...
    99+
    2023-05-17
    C++强制类型转换 C++类型转换
  • C++如何强制类型转换
    小编给大家分享一下C++如何强制类型转换,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!一、C强制转换C语言中的强制转换主要用于普通数据类型、指针的强制转换,没有类...
    99+
    2023-06-25
  • C++超详细讲解泛型
    目录1.了解泛型编程2.函数模板2.1简单示例2.2多个模板参数2.3模板实例化2.4模板和普通函数同时存在2.5函数模板不支持定义和声明分离3.类模板3.1简单示例3.2成员函数声...
    99+
    2024-04-02
  • JavaScript中类型的强制转换与隐式转换详解
    目录一、隐式转换双等号里的转换 Boolean 类型转换 "+" 与 "-" 二、强制类型转换 new String 与 ' ' 总结一、隐式转换 以下语句的执行结果是什么? A...
    99+
    2024-04-02
  • C语言强制类型转换规则实例详解
    目录整形之间的强制转换无符号转有符号有符号转无符号不同长度数字转化中的截断整形与浮点数的强制类型转换总结整形之间的强制转换 在强制类型转换中,我们常用的整形强制转换有无符号和有符号类...
    99+
    2024-04-02
  • C++primer超详细讲解泛型算法
    目录初识泛型算法只读算法写容器算法定制操作lambda表达式lambda捕获和返回再探迭代器插入迭代器iostream迭代器反向迭代器初识泛型算法 只读算法 只读取输入范围内的函数,...
    99+
    2024-04-02
  • C++中如何强制类型转换
    C++中如何强制类型转换,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。1. c强制转换与c++强制转换 c语言强制类型转换主要用于基础的数据类型间的转换,语法为:...
    99+
    2023-06-20
  • c++类的隐式转换与强制转换重载详解
    在写这篇文章之前,让我们先回顾一下编译器通过匹配过程确定调用哪一个函数的匹配顺序:(1)寻找和使用最符合函数名和参数类型(包括返回值)的函数,若找到则调用;(2)否则,寻找一个函数模...
    99+
    2022-11-15
    隐式转换 强制转换 c++
  • C++详细讲解引用类型
    目录一、C++中的引用类型二、如何使用C++中的引用类型一、C++中的引用类型 在以严蔚敏老师的《数据结构》为代表的诸多数据结构的书中,都出现了C++引用这一用法,所以在学习数据结构...
    99+
    2024-04-02
  • C#强制类型转换与泛型怎么理解
    本篇内容主要讲解“C#强制类型转换与泛型怎么理解”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C#强制类型转换与泛型怎么理解”吧!C# 强制类型转换和普通对象一样,泛型类的对象也可以采用强制类型...
    99+
    2023-06-17
  • Reactjsx转换与createElement使用超详细讲解
    目录jsx的转换16.x版本及之前17.x版本及之后React.createElement源码React.Component 源码总结jsx的转换 我们从 react 应用的入口开始...
    99+
    2022-11-13
    React jsx转换 React createElement
  • C语言隐式类型转换与强制类型转换的方法是什么
    本篇内容主要讲解“C语言隐式类型转换与强制类型转换的方法是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C语言隐式类型转换与强制类型转换的方法是什么”吧!类型转换数据有不同的类型,不同类型数...
    99+
    2023-06-25
  • C++强制类型转换的四种方式
    目录1 C++类型转换本质1.1 自动类型转换(隐式)1.2 强制类型转换(显式)1.3 类型转换的本质1.4 类型转换的安全性2 四种类型转换运算符2.1 C语言的强制类型转换与C...
    99+
    2024-04-02
  • C++强制类型转换(static_cast、dynamic_cast、const_cast、reinterpret_cast)
    目录1. c强制转换与c++强制转换 2. static_cast、dynamic_cast、const_cast、reinterpret_cast dynamic_cast con...
    99+
    2024-04-02
  • C++的类型转换(强转)你了解吗
    目录静态类型转换动态类型转换常量转换重新解释转换总结静态类型转换 关键字: static_cast 1,允许内置数据类型之间的转换 char a = 'a'; d...
    99+
    2024-04-02
  • C++超详细讲解字符串类
    目录一、历史遗留问题二、解决方案三、标准库中的字符串类四、字符串循环右移五、小结一、历史遗留问题 C 语言不支持真正意义上的字符串C 语言用字符数组和一组函数实现字符串操作C 语言不...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作