C++ c++;动态浇铸 类CBase{}; 类派生:公共CBase{}; CBase b; CBase*pb; c衍生d; CDerived*pd; pb=动态_投射(&d);//确定:导出到基 pd=动态施法(&b);//错误:从基到派生

C++ c++;动态浇铸 类CBase{}; 类派生:公共CBase{}; CBase b; CBase*pb; c衍生d; CDerived*pd; pb=动态_投射(&d);//确定:导出到基 pd=动态施法(&b);//错误:从基到派生,c++,dynamic-cast,C++,Dynamic Cast,我知道“从基础到衍生”的演员阵容是错误的。但其内在原因是什么?内在的逻辑原因是什么?我想,如果没有更多的解释,很难记住这一点。 谢谢大家! 派生类可以比基类有更多的“行为”。更多的成员函数,更多的成员数据,等等。如果您将基类强制转换为派生类,然后尝试将其视为派生类,那么您将尝试让它做它不能做的事情。因为您试图使基类的实例执行只有派生类才知道如何执行的操作。首先,CBase必须是多态的,才能在此处使用dynamic\u cast(也就是说,它必须至少有一个virtual成员函数)。否则,您不能使用

我知道“从基础到衍生”的演员阵容是错误的。但其内在原因是什么?内在的逻辑原因是什么?我想,如果没有更多的解释,很难记住这一点。
谢谢大家!

派生类可以比基类有更多的“行为”。更多的成员函数,更多的成员数据,等等。如果您将基类强制转换为派生类,然后尝试将其视为派生类,那么您将尝试让它做它不能做的事情。因为您试图使基类的实例执行只有派生类才知道如何执行的操作。

首先,
CBase
必须是多态的,才能在此处使用
dynamic\u cast
(也就是说,它必须至少有一个
virtual
成员函数)。否则,您不能使用
动态\u cast

也就是说,将
&b
转换为
CDerived*
并没有错:
pd
将是一个空指针

dynamic_cast
具有一个有用的属性,即当强制转换失败时(即,如果指针指向的对象不是目标类型),它将生成一个空指针。这允许您测试对象的实际类型。例如:

class CBase { };
class CDerived: public CBase { };

CBase     b; 
CBase*    pb;
CDerived  d; 
CDerived* pd;

pb = dynamic_cast<CBase*>(&d);     // ok: derived-to-base
pd = dynamic_cast<CDerived*>(&b);  // wrong: base-to-derived
CBase-b;
c衍生d;
CBase*pb=&b;
CBase*pd=&d;
CDerived*xb=动态(pb);//xb为空!
CDerived*xd=动态(pd);//xd指向d!

如果您使用的是
static\u cast
,那么您的代码可能不正确,因为它在没有执行任何运行时类型检查的情况下进行了强制转换,这意味着无法测试强制转换是否成功。如果需要向下转换类层次结构,并且不确定对象是否属于要转换的派生类型,则必须使用
dynamic\u cast

进行派生到基的转换,您根本不需要(通常也不希望)显式指定转换:

CBase b;
CDerived d;

CBase* pb = &b;
CBase* pd = &d;

CDerived* xb = dynamic_cast<CDerived*>(pb); // xb is null!
CDerived* xd = dynamic_cast<CDerived*>(pd); // xd points to d!
派生类型转换的基础并不是真的错误,尽管您通常更愿意避免它。这背后的原因相当简单:指向base的指针可以指向实际的base对象或从中派生的任何对象。如果您打算这样向下转换,通常需要检查转换是否成功。在您给定的特定情况下,它不会成功,因此分配的内容(动态转换的结果)将只是一个空指针


大多数情况下,您希望在基类中为类的对象指定一个完整的接口,因此很少需要进行向下转换。

pd
是类型为
CDerived*
的指针。因此,
pd
定点对象需要涉及两个子对象(即基础和派生)。但有了这句话-

CDerived d;
CBase *pb = &d;   // perfectly fine
pd=dynamic_cast(&b);
这里,
pd
仅指向一个基本子对象。没有指向子对象的局部方式。所以,这是错误的。

因为猫是动物,但动物不一定是猫(可能是狗)。
pd = dynamic_cast<CDerived*>(&b);