Casting -为什么我应该为Upcasting做这个

Casting - Why Should I do it for Upcasting

本文关键字:Upcasting 为什么 我应该 Casting      更新时间:2023-10-16

我一直在阅读这个网站上的其他一些帖子,他们提到dynamic_cast和static_cast对于上行转换都是安全的。

为什么需要这些来进行向上转换?

例如,如果类B派生自类A,则

A * ptr = new B ();

仍然可以工作,并且表现得像a类型的对象(我也是来自Java背景,不需要进行上转换的转换)。

我还在这个网站上读到dynamic_cast不需要向下转换[在问题"何时应该使用static_cast, dynamic_cast, const_cast和reinterpret_cast ?"]. 再一次,我认为只有当你向下转换时才真正需要转换,因为向上转换是自动发生的。

我错在哪里?

如果您有复杂的继承层次结构,默认的向上转换行为可能不起作用。例如:

struct A {};
struct B : A {};
struct C : A {};
struct D : B, C {};

在该层次结构中,类型为D的对象有两个不同的类型为A的碱基。从D*A*的转换是不明确的。对于这种情况,可以强制执行中间步骤

A *p = static_cast<B*>(d);   // Give me the 'A' subobject within 'B'
类似地,如果有一个函数具有多个重载,可以采用基类型或派生类型,并且需要调用采用基类型的版本(注意:这里有代码气味!),那么可以使用强制类型转换来直接重载解析。同样,如果您需要直接重载解析,那么您可能在其他地方做错了。

除了极端情况(即当默认的向上转换不起作用时),真的没有理由显式地使用强制转换操作,我实际上不建议这样做,因为强制转换应该是一个警示灯,过度使用它们可能会使它们正常并且在读取代码时不会发出警报。

在多重继承的情况下(Java实际上没有),您可能会调整您的"this"指针。在这种情况下,reinterpret_cast是不安全的,这就是他们试图通过说static_cast和dynamic_cast是安全的来强调的。

作为一个小提示,在对一个要移植到Android-without-dynamic_cast的代码库的调查中,我发现了127个dynamic_cast,其中122个实际上是不必要的。

为什么需要这些来进行向上转换?

它们不是,并且将它们用于向上强制转换(IMHO)是误导:不需要强制转换是有原因的:逻辑上,子类对象是超类的实例。

总之,我不鼓励显式向上转换。对于坚持这一点的人,我至少要求一致性:在的任何地方使用显式的向上转换,包括初始化:

A * ptr{static_cast<A*>(new B)};

大多数人会认为这很愚蠢。