首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >从基座下移导出分段故障

从基座下移导出分段故障
EN

Stack Overflow用户
提问于 2019-05-22 13:07:39
回答 2查看 181关注 0票数 0

我正在学习动态铸造和搜索很多网站,我得出的结论是,动态铸造可以从基础到派生到基础。但是,当我从Base转换到派生时,它会出现分段错误。这是代码:

我希望从上面的“从A”,但它给了我一个从D,即使在铸造后

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class A
{
  public:
  virtual ~A(){} 
  virtual void print()
  {
    std::cout << "from A"<<std::endl;
  }
  };
class B:  virtual public A
{
  public:
    void print()
  {
    std::cout << "from B"<<std::endl;
  }
};       
class C: virtual public A
{
  public:
    void print()
  {
    std::cout << "from C"<<std::endl;
  }
};      
class D: public B, public C
{
  public:
    void print()
  {
    std::cout << "from D"<<std::endl;
  }
};


int main(){
    A* b = new B;
    A* c = new C;
    A* d = new D;
    A* a = new A;

    B* down = dynamic_cast<B*>(a);  // this gives me problem
    down->print();

    A* up= dynamic_cast<A*>(d); // upcasten dont print from A either
    up->print();
EN

回答 2

Stack Overflow用户

发布于 2019-05-22 13:27:41

当使用dynamic_cast转换指针时,您需要检查结果指针,以确定转换在访问它之前是否有效。访问无效指针会导致未定义的行为。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    B* down = dynamic_cast<B*>(a);
    if (down == 0) {
        std::cerr << "a is not a B!\n";
    } else {
        down->print();
    }

您不需要使用dynamic_cast进行“向上转换”。允许将派生的内容分配给父级。如果不存在这种关系,您将得到一个编译时错误。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    A* up= d;
    up->print();

由于print是一个虚拟方法,所以up->print()解析为派生的实现。但是,如果希望看到基类的实现,可以显式地调用它。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    d->A::print();

在网上试试!

票数 2
EN

Stack Overflow用户

发布于 2019-05-22 13:13:58

从基础到派生和从派生到基础的转换能力不是dynamic_cast的独特特征。关键特性是dynamic_cast在运行时执行这种转换,检查大多数派生对象实际上匹配(或实际上包含)所需的目标类型。这意味着,如果转换失败,错误也是运行时错误,您的程序应该预先设置以在运行时处理此类错误。

这些错误可能是什么?dynamic_cast可能报告错误,方法是:如果在指针类型之间转换(例如X*Y* ),则返回空指针;如果在引用类型之间转换(如X&Y& ),则抛出std::bad_cast异常。

使用静态类型aA*转换为B*可以生成指向B的有效指针或null。后者正是在您的示例中发生的:a实际上指向一个类型为A的完整对象,其中没有B类型的子对象。因此,cast返回空指针,然后立即用于调用成员函数down->print()。任何取消引用空指针值的尝试都是UB (未定义的行为),这很可能表现为分段错误。

保护您的程序不受这种分段错误的影响很容易:只需检查返回的值是否为空:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
B* down = dynamic_cast<B*>(a);
if (down)
{
    // Use down all you want
}
else
{
    // Report an error, skip some actions
    // or return from the function.
    // But don't use `down`!
}

至于打印"from D",这是因为print方法被声明为虚拟的。这意味着来自大多数派生类的实现将被调用,即使您通过指向基子对象的指针调用它。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56265039

复制
相关文章
如何在 Git 上更改分支名称?
在 Git 版本控制系统中,分支是非常重要的概念。分支允许你在项目中进行并行开发和实验,同时保持主分支的稳定性。有时候,你可能需要更改已存在的分支名称,例如纠正拼写错误或者为了更好地描述分支的内容。本文将详细介绍如何在 Git 上更改分支名称。
网络技术联盟站
2023/06/19
1.9K0
如何在 Git 上更改分支名称?
更改Linux网卡名称
转载自:https://blog.csdn.net/yeziand01/article/details/88424624
zy010101
2019/07/02
5.1K0
更改Linux网卡名称
Oracle 更改表名称的几种方式
ALTER TABLE old_table_name RENAME TO new_table_name;(大写为系统命令)
全栈程序员站长
2022/08/29
4.7K0
更改WordPress插件的菜单名称
如果您想在不直接编辑插件的情况下更改WordPress内部管理菜单的名称,您可以使用$menuWordPress管理员中存在的全局变量。操作此数据结构将允许您更改由任何插件添加的管理菜单的文本或名称。这在您希望提供项目内容的清晰度或为客户端提供更好的管理UX的情况下非常有用。
许都博客
2021/06/15
4K0
Github更改账户名称/仓库地址/个人链接后缀
注意:在public profile中修改的name,是主页个人名字,不是仓库地址后缀!!!
浩Coding
2019/07/03
11.4K0
如何在NLP中有效利用Deep Transformer?
2017年,谷歌在“Attention is all you need”一文中首次提出了完全基于self-attention(自注意力)机制的transformer模型,用于处理序列模型的相关问题,如机器翻译等。传统的神经机器翻译模型大都是采用RNN或者CNN作为encoder-decoder模型的基础,而Transformer模型则摒弃了固有的模式,采用完全并行化的结构,在提升了模型的性能的同时提高了训练的速度,目前已经被推广到多项自然语言处理的相关任务当中。
AI科技评论
2020/02/14
9570
如何在NLP中有效利用Deep Transformer?
如何在Linux中更改SSH端口?
SSH(Secure Shell)是一种安全的远程登录协议,它允许您通过网络远程连接到Linux系统并进行管理操作。默认情况下,SSH使用22端口进行通信。然而,为了增强系统的安全性,有时候我们需要更改SSH端口,以减少潜在的攻击。
网络技术联盟站
2023/05/25
9.4K0
如何在Linux中更改SSH端口?
如何在 Linux 中更改主机名?
在 Linux 系统中,主机名是用于标识和区分网络上的不同计算机的名称。默认情况下,Linux 发行版会分配一个主机名给您的计算机,但是有时候您可能需要根据自己的需求更改主机名。在本文中,我们将详细介绍如何在 Linux 中更改主机名,以及更改主机名后可能涉及到的其他配置。
网络技术联盟站
2023/06/09
8.8K0
如何在 Linux 中更改主机名?
linux中有选择的删除目录中的文件
某些场景下我们需要删除目录下指定类型,后缀的文件。这时候就需要一些小技巧。 首先我们先要了解一下模式匹配。在Linux中,shell模式是由以下特殊字符组成的字符串,称为wildcards或者meta
入门笔记
2022/06/02
3K0
如何在 Linux 中更改 Nginx 80 端口?
Nginx 是一个开源的轻量级 Web 服务器替代 apache 来处理高流量的网站。
网络技术联盟站
2022/06/21
5.4K0
如何在 Linux 中更改 Nginx 80 端口?
如何在Ubuntu 14.04上更改PHP设置
PHP是一种服务器端脚本语言,被许多流行的CMS和博客平台使用,如WordPress和Drupal。它也是流行的LAMP和LEMP堆栈的一部分。在设置基于PHP的网站时,更新PHP配置设置是一项常见任务。找到确切的PHP配置文件可能并不容易。有多个PHP安装在服务器上正常运行,每个安装都有自己的配置文件。知道要编辑哪个文件以及当前设置是什么可能有点神秘。
彼岸轮回
2018/09/25
1.7K0
如何在 Linux 中更改 Apache HTTP 端口?
Apache Web Server 是一个免费的开源跨平台 Web 服务器应用程序,用于通过 Internet 提供内容。
网络技术联盟站
2022/06/21
6.3K0
如何在 Linux 中更改 Apache HTTP 端口?
如何在Linux中更改用户ID?
在Linux系统中,每个用户都有一个唯一的用户ID(User ID),用于标识和管理用户的权限和资源访问。有时候,我们需要更改用户ID,可能是为了解决冲突、重组用户组或其他管理需求。本文将详细介绍如何在Linux中更改用户ID的几种方法。
网络技术联盟站
2023/06/08
8.4K0
如何在Linux中更改用户ID?
使用Python实现批量更改文件夹下图片的名称
前几天在Python白银交流群有个叫【belongs】的粉丝问了一个使用Python实现批量更改文件夹下图片的名称的问题,如下图所示。
前端皮皮
2022/08/17
2.6K0
使用Python实现批量更改文件夹下图片的名称
点击加载更多

相似问题

在CKEditor中有选择地触发更改事件

12

如何在Coq中有选择地重写?

15

选择名称匹配,如80%

35

如何在FosUserbundle中有选择地禁用注册?

22

如何在python中有选择地深拷贝?

11
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文