c++11 - 当您在具有相同基类的派生类之间进行动态转换时会发生什么?
问题描述
我试图弄清楚当你dynamic_cast
从一个派生类到另一个派生类时会发生什么。为什么下面的代码会引发分段错误?请注意,我并没有尝试将此代码用于任何事情。我只是想了解正在发生的事情。
还值得注意的是,相同的代码使用static_cast
. 我似乎找不到任何文档来详细说明这里发生的事情。有人可以解释一下吗?
struct base
{
virtual void printing(){cout<<"base printing"<<endl;};
};
struct derived_1 :public base
{
virtual void printing(){cout<<"derived_1 printing"<<endl;};
};
struct derived_2 :public base
{
virtual void printing(){cout<<"derived_2 printing"<<endl;};
};
int main()
{
base * b = new derived_2();
derived_1 *d_1 = dynamic_cast<derived_1*>(b);
// calling printing raises segmentation fault
d_1->printing();
}
解决方案
转换为derived_1
将失败,因为derived_2
是一个 base
对象但不是一个derived_1
对象。因此,您不能“转换”到所需的指针类型。
并不是说无论何时dynamic_cast
失败,它都会返回一个nullptr
(引用类型除外)。这最终会导致代码中的分段错误(通常,我建议您始终if (d_1 != nullptr)
在使用动态转换的对象之前添加 a )。
更新:
顺便说一句,这实际上是一个很好的例子dynamic_cast
。即使您可能很想static_cast
在您的示例中使用它并且它会编译,但您将处理未定义的行为。Usingstatic_cast
将在没有打嗝的情况下编译,但实际上您将使用损坏的类型。假设derived_1::printing()
访问一些变量derived_1::a
,该变量在derived_2
. derived_2
通过将一个对象(没有)静态转换a
为一个derived_1
对象d_1
,你会错误地假设d_1
包含一些有效a
的,事实并非如此。
例子:
// ...
struct derived_1 :public base
{
const int a = 123;
void printing() override {cout<<"derived_1 printing " << endl;}
void foo() { cout << "Foo using constant = " << a << endl; }
};
// ...
int main()
{
base * b = new derived_2();
derived_1 *d_1 = static_cast<derived_1*>(b);
d_1->printing(); // Will call derived_2::printing(), which is not what you expect!
d_1->foo(); // Won't show a = 123 but some nonesense (mostly 0),
// because a is not defined in derived_2.
}
推荐阅读
- c# - @Url.Action 传递当前 url 的 id 段
- python - 比较列表和字典
- javascript - 使用 SVG 路径作为另一个路径的“骨架”(弯曲路径)
- python - 检查 pandas csv 块是否包含字符串
- python - 通过串行接收正确长度的数据
- ios - 一次选择多个单元格的 UIcollection 视图错误
- css - 溢出时:auto,看不到 padding-bottom
- python - 在 Jupyter 笔记本上导入 Xgboost 时遇到这个简单的问题
- github - 如何在 Github 中创建子文件夹存储库
- amazon-web-services - Cloudformation AWS IAM 角色,带和不带 RoleName 参数