我正在经历“Multiple Inheritance for C++ by Bjarne Stroustrup, Published in the May 1999 issue of "The C/C++ Users Journal"”。以下摘录来自同一页(第5/17页),
4.4投射
显式和隐式转换还可能涉及使用delta:
修改指针值class A { void f(); }; class B { int f(); }; class C : A, B { }; C* pc; B* pb; pb = (B*)pc; // pb = (B*)((char*)pc+delta(B)) pb = pc; // pb = (B*)((char*)pc+delta(B)) pc = pb; // error: cast needed <-------------------- HERE pc = (C*)pb; // pc = (C*)((char*)pb-delta(B))
他告诉我们pb = pc
可以在不明确强制转换的情况下完成。这肯定意味着隐式处理了转换。然后,
pc = pb
指针时,为什么需要进行投射? 修改
Jonathan Mee将此问题标记为“What Type of Cast to Go from Parent to Child?”的副本。我很害怕,我不同意。我的问题是, 为什么要投射以及这条规则指示我们施放或不施放 。我认为背后的逻辑可能是相同的,但概念完全不同。在他的问题中,他怀疑(坚持不使用动态演员)使用dynamic_cast和static_cast。我的疑问仍然是他背后的一些步骤。
答案 0 :(得分:3)
它与我们知道对象所具有的类型有关。每个C
也是B
,因此转换始终有效(隐式)。
每个B
都不是C
的一部分,因此您必须告诉编译器您确定此特定转换将起作用。这是使用显式演员。
答案 1 :(得分:2)
The rules如下:
- 空指针可以转换为任何类型的指针
- 指向任何类型的指针都可以转换为void指针。
- 指针upcast:指向派生类的指针可以转换为可访问且明确的基类的指针,而无需修改其
const
或volatile
限定。
因此当向上转播从C*
转换为B*
时,不需要显式转换。但是因为从B*
转换为C*
是指针向下转换,可以使用C样式转换,但首选以下之一:
B*
且new_type为C*
,则可以使用dynamic_cast
,此次运行时检查将执行,并且 1 < /强>:
- 检查由表达式指向/标识的派生对象最多的对象。如果在该对象中,表达式指向/指向Derived的公共基础,并且如果只有一个派生类型的子对象是从由表达式指向/标识的子对象派生的,则转换结果/指向该派生子对象。 (这被称为&#34; downcast&#34;。)
- 否则,如果表达式points /引用最派生对象的公共基础,并且同时,最派生的对象具有Derived类型的明确公共基类,则转换点的结果/指的是Derived(这被称为&#34; sidecast&#34;。)
- 否则,运行时检查失败。如果在指针上使用dynamic_cast,则返回类型为new_type的空指针值。
醇>
reinterpret_cast
可以使用,并且将永远成功。但只有在给定B
为AliasedType并且C
为DynamicType时,满足其中一个条件,即2 nd 项目符号时,才会定义结果的使用允许垂头丧气:
- AliasedType是(可能是cv限定的)DynamicType
- AliasedType和DynamicType都是(可能是多级,可能是每个级别的cv限定)指向相同类型的指针T
- AliasedType是DynamicType
的(可能是cv限定的)有符号或无符号变体- AliasedType是一种聚合类型或联合类型,它将上述类型之一保存为元素或非静态成员(包括,递归地,包含联合的子聚合和非静态数据成员的元素):这使得它在给定指向其非静态成员或元素的指针的情况下,可以安全地获取指向结构或联合的可用指针。
- AliasedType是(可能是cv限定的)DynamicType
的基类- AliasedType为
char
或unsigned char
:这允许将任何对象的对象表示检查为unsigned char数组。
B*
实际上是多态地处理C
对象时,也可以使用static_cast
。如果不是这种情况并且尝试static_cast
,则会导致未定义的行为。答案 2 :(得分:1)
好吧,编译器知道指向C
的指针可以像继承的class A
或B
那样被引用 - 所以将向上转换为{{1 }}或A
可以隐式完成。另一方面,编译器不知道指针是B
的对象。它可以是一个不同的类,也继承C
。通过添加一个演员,你基本上是说&#34; 不要担心编译器 - 我知道它实际上是一个类型C &#34;。
答案 3 :(得分:1)
在你的情况下,这很简单。您尝试将指向类B
的对象的指针指向指向类C
的对象的指针。
本身,你不能这样做,因为类C
的对象也提供了类A
的功能,类B
的对象没有。因此,期望对象B
的类C
的对象的使用未定义,因为B
无法提供C
所拥有的所有内容。