static_cast与dynamic_cast到底是什么?

static,cast,dynamic · 浏览次数 : 0

小编点评

**结论:** 子类指针可以安全地转换为父类指针,两种方法都是安全的:`static_cast` 和 `dynamic_cast`。 **作者觉得通俗易懂的理解:** 1. **static_cast** 是编译器在编译阶段对类型进行检查的技术。当我们使用 `static_cast` 将父类指针转换为子类指针时,编译器会进行类型检查,确保转换是安全的。 2. **dynamic_cast** 在运行时通过动态类型检查将父类指针转换为子类指针。当我们使用 `dynamic_cast` 将父类指针转换为子类指针时,运行时会检查父类指针指向的具体类型,确保转换是安全的。 **使用示例:** ```cpp class B { public: virtual ~B() {} }; class D : public B { public: D() { cout << "D" << endl; } }; int main() { B* pb = new B; D* p3 = dynamic_cast(pb); if (p3 != nullptr) { cout << "成功了" << endl; } else { cout << "失败了" << endl; } return 0; } ``` **运行结果:** ``` 成功了 ``` **说明:** * `static_cast` 只能用于强制类型转换。 * `dynamic_cast` 可以用于强制类型转换,也可以用于安全类型转换。 * 使用 `dynamic_cast` 需要在转换结果的类型之前进行类型检查。

正文

写这个随笔说一下C++的static_cast和dynamic_cast用在子类与父类的指针转换时的一些事宜。首先,【static_cast,dynamic_cast】【父类指针,子类指针】,两两一组,共有4种组合:用 static_cast 父类转子类、用 static_cast 子类转父类、使用 dynamic_cast 父类转子类、用 dynamic_cast 子类转父类。搞清楚了这4种情况,这篇文章的任务也就达成了。

先说结论,后面给出一个作者觉得通俗易懂的理解:

1. static_cast : 父类转子类:可以转,不报错,不安全;

2.static_casrt : 子类转父类:可以转,不报错,安全;

3.dynamic_cast : 父类转子类 :

  a)若父类中没有虚函数,不能转,编译报错;

  b)若父类至少有一个虚函数则可以转,不报错;但:

    b.1)若父类指针指向的确实是一个子类对象,则dynamic_cast返回该子类对象的地址;

    b.2)若父类指针指向的是父类对象,则dynamic_cast返回空指针nullptr;

 4.dynamic_cast:子类转父类:可以转,不报错,安全。

 

总体来看,子类指针父类指针无论怎样都是安全、允许的(上面的2、4),所以static_cast和dynamic_cast都可以安全使用。

再说上面的1、3。 其实,static_cast相当于我们程序员对编译器的一种承诺:我们清楚地知道这样转存在的任何风险,并且我们能够接受这样的风险。所以,当我们用static_cast将父类指针转换成子类指针时,编译器不报错。而dynamic_cast是在运行时执行类型转换,用于将基类的指针安全地转换成派生类的指针,也就是说,dynamic_cast会进行动态类型检查。dynamic_cast相当于给程序员提供了一种安全的机制,让程序员能够安全地使用父类指针的动态类型。

下面举一个使用dynamic_cast(以上3中的b)的例子。首先给出父类和子类的定义:

class B
{
public:
    virtual ~B() {};
};

class D : public B
{

};

若有以上类的定义:

代码1:

B* pb = new B;
if( D* p3 = dynamic_cast<D*>(pb) )   
{
    cout << "成功了" << endl;
  //若程序到此处,则程序员知道,pb指向的实际上是子类对象,可以使用p3
}
else {
    cout << "失败了" << endl;
  //若程序到此处,则程序员知道,pb指向的实际上是父类对象,使用pb
}

 

输出:失败了。因为动态运行时,pb指向的是父类,并不是子类。

代码2:

B* pb = new D;
if( D* p3 = dynamic_cast<D*>(pb) )   
{
    cout << "成功了" << endl;
  //若程序到此处,则程序员知道,pb指向的实际上是子类对象,可以使用p3
}
else {
    cout << "失败了" << endl;
  //若程序到此处,则程序员知道,pb指向的实际上是父类对象,使用pb
}

输出:成功了。

 

与static_cast与dynamic_cast到底是什么?相似的内容:

static_cast与dynamic_cast到底是什么?

写这个随笔说一下C++的static_cast和dynamic_cast用在子类与父类的指针转换时的一些事宜。首先,【static_cast,dynamic_cast】【父类指针,子类指针】,两两一组,共有4种组合:用 static_cast 父类转子类、用 static_cast 子类转父类、使用

面试官:告诉我为什么static和transient关键字修饰的变量不能被序列化?

一、写在开头 在上一篇学习序列化的文章中我们提出了这样的一个问题: “如果在我的对象中,有些变量并不想被序列化应该怎么办呢?” 当时给的回答是:不想被序列化的变量我们可以使用transient或static关键字修饰;transient 关键字的作用是阻止实例中那些用此关键字修饰的的变量序列化;当对

c# aveva marine link folder

public class LinkWorld { public static DbElement LinkWLD => Aveva.Pdms.Database.DbType.Design.FindElements(DbElementTypeInstance.LINKWLD).FirstOrDefau

[转帖]静态路由实例:如何在 macOS、FreeBSD、Linux、Windows、Cisco 和 VMware 上添加静态路由

https://sysin.org/blog/static-routing/ 学习一下呢. 本文描述主流系统和产品添加静态路由的方法,一些具备 WEB 管理界面的产品不在讨论范围,比如防火墙、路由器等多数产品具备直观的操作界面。 macOS 1、添加路由命令(临时) 与 Linux 类似,但是网关没

5 分钟理解 Next.js Static Export

5 分钟理解 Next.js Static Export 在本篇文章中,我们将介绍 Next.js 中的 Static Export 功能,以及它是如何工作的。我们将介绍一些相关的基本概念,以及在 Next.js 中如何使用 Server Components 和 Client Components

文盘Rust -- 生命周期问题引发的 static hashmap 锁

2021年上半年,撸了个rust cli开发的框架,基本上把交互模式,子命令提示这些cli该有的常用功能做进去了。项目地址:[https://github.com/jiashiwen/interactcli-rs。](https://github.com/jiashiwen/interactcli-

c# aveva marine 批量导出图纸到dxf格式

获取图纸数据库 查看代码 public static Dictionary

[转帖]Linux系统多网卡环境下的路由配置

https://www.cnblogs.com/connect/p/linux-static-route.html Linux下路由配置命令 1. 添加主机路由 route add -host 192.168.1.11 dev eth0 route add -host 192.168.1.12 gw

基于React的SSG静态站点渲染方案

基于React的SSG静态站点渲染方案 静态站点生成SSG - Static Site Generation是一种在构建时生成静态HTML等文件资源的方法,其可以完全不需要服务端的运行,通过预先生成静态文件,实现快速的内容加载和高度的安全性。由于其生成的是纯静态资源,便可以利用CDN等方案以更低的成

[转帖]ck的离线安装

下载 下载地址: https://repo.clickhouse.tech/tgz/stable/ 下载的包: clickhouse-common-static clickhouse-server clickhouse-client 单机安装 tar -zxvf clickhouse-common-