关于动态转换和(菱形)继承
Posted
技术标签:
【中文标题】关于动态转换和(菱形)继承【英文标题】:About dynamic cast and (diamond) inheritance 【发布时间】:2021-06-11 20:01:32 【问题描述】:我截取了以下代码:
#include <iostream>
#include <typeinfo>
using namespace std;
class B
int i;
public:
B()i = 1;
virtual int get_i()return i;
;
class D: virtual public B
int j;
public:
D()j = 2;
int get_i()return B::get_i() + j;
;
class D2: virtual public B
int j2;
public:
int get_i()return B::get_i() + j2;
;
class MM: public D, public D2
int x;
public:
MM()
x = D::get_i() + D2::get_i();
int get_i()return x;
;
int main()
B* o = new MM();
cout << o->get_i() << "\n";
MM* p = dynamic_cast<MM*>(o);
if(p) cout << p->get_i() << "\n";
D* p2 = dynamic_cast<D*>(o); /// Why does this dynamic_cast not return NULL?
if(p2)
cout << p2->get_i() << "\n";
The output will be:
我的问题是:为什么标记线上的dynamic_cast会成功?所以,如果我有这样的层次结构:
class Grandpa...;
class Dad : public Grandpa...;
class Son: public Dad...;
当然
Grandpa* grandpa = new Son();
没问题。
请问dynamic_cast
:
Dad* dad = dynamic_cast<Dad*>(grandpa);
总是成功?
这在某种程度上是合乎逻辑的,只要 Dad
指针始终可以指向 Son
对象,但我以前从未见过这种情况,我想保证我可以将其作为一般规则。
【问题讨论】:
旁注:C++ 中的继承意味着"Is-A" 关系。这意味着如果爸爸从爷爷那里继承,那么爸爸就是爷爷。这也意味着儿子是爸爸和爷爷。有点介意-,是吗? 【参考方案1】:为什么标记线上的dynamic_cast会成功?
因为对象的动态类型有一个D
基数。
请问下面的dynamic_cast:
Dad* dad = dynamic_cast<Dad*>(grandpa);
总是成功?
在Grandpa* grandpa = new Son();
的前提下,是会成功的。
但在其他情况下不会成功,例如:
Grandpa gp;
Grandpa* grandpa = &gp;
Dad* dad = dynamic_cast<Dad*>(grandpa); // is null
【讨论】:
【参考方案2】:是的,只要超类类型指针指向的对象确实是您要转换的类型的对象,dynamic_cast 就会成功。如果不是该类型的对象,otoh,dynamic_cast 将返回一个空指针。
【讨论】:
以上是关于关于动态转换和(菱形)继承的主要内容,如果未能解决你的问题,请参考以下文章
C++进阶:继承C++为什么要引入继承 | 继承概念及定义 | 基类和派生类对象赋值转换 | 继承中的作用域 | 派生类的默认成员函数 | 继承与友元/静态成员 | 复杂的菱形继承及菱形虚拟继承
C++进阶:继承C++为什么要引入继承 | 继承概念及定义 | 基类和派生类对象赋值转换 | 继承中的作用域 | 派生类的默认成员函数 | 继承与友元/静态成员 | 复杂的菱形继承及菱形虚拟继承
C++进阶:继承C++为什么要引入继承 | 继承概念及定义 | 基类和派生类对象赋值转换 | 继承中的作用域 | 派生类的默认成员函数 | 继承与友元/静态成员 | 复杂的菱形继承及菱形虚拟继承
C++进阶:继承C++为什么要引入继承 | 继承概念及定义 | 基类和派生类对象赋值转换 | 继承中的作用域 | 派生类的默认成员函数 | 继承与友元/静态成员 | 复杂的菱形继承及菱形虚拟继承