我有以下代码:
using namespace std;
class BaseOk
{
public:
virtual void ImplementMe()
{
};
};
class DerivedOk : public BaseOk
{
public:
void ImplementMe()
{
}
};
class CBase { };
class CDerived: public CBase { };
int main()
{
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 -> this doesn't compile
// Polymorphic case
BaseOk b2; BaseOk* pb2;
DerivedOk d2; DerivedOk* pd2;
pb2 = dynamic_cast<BaseOk*>(&d2); // ok: derived-to-base
pd2 = dynamic_cast<DerivedOk*>(&b2); // wrong: base-to-derived -> this returns a NULL pointer
}
指针“pd”的行执行向下转换,我同意它应该失败,因为结果是完全不同的对象。 我的问题是:为什么该行中的dynamic_cast根本不编译而不是只返回一个NULL指针?
我正在使用MSVC2012编译器
答案 0 :(得分:2)
为什么该行中的
dynamic_cast
根本没有编译 只返回一个NULL指针?
将此视为功能/设施而非限制。
dynamic_cast
是一种机制,我们可以根据指针/引用找到对象的RTTI(运行时类型信息)。
现在假设一个类完全没有多态(即不包含任何virtual
方法),那么dynamic_cast
总是会失败。
这意味着你不必使用传递概率为0的dynamic_cast
。 为什么要在编译时知道的事情上浪费机器周期?这就是为什么编译器会立即为您提供设施。
这还有另一个隐藏的优势。假设您正在使用带有引用的dynamic_cast
,如果它失败则抛出异常。是否有人想要处理在编译时已知的事情的异常!
答案 1 :(得分:2)
在指向非多态类型的指针上使用dynamic_cast
是一个错误。这是一个可诊断的规则,所以你应该得到一个编译时错误。
在指向不可转换为目标类型的多态类型的指针上使用它不是错误,并且在编译时通常无法检测到。它有明确定义的行为,给出一个空指针。