何时以及如何决定是否使用演员阵容?

When and how is it decided to either use a cast or not?

我正在浏览“Multiple Inheritance for C++ by Bjarne Stroustrup, Published in the May 1999 issue of "The C/C++ Users Journal"”。以下摘录自同(第5/17页),

4.4 Casting

Explicit and implicit casting may also involve modifying a pointer value with a 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 可以在不显式转换的情况下完成。这绝对意味着转换是隐式处理的。那么,

  1. 为什么当我们尝试 pc = pb 指针时,是否需要强制转换?
  2. 指导这个的规则是什么以及在哪里?
  3. 是否与incrementing/decrementing指针的delta值有关?

编辑

Jonathan Mee marked this question as the duplicate of "”。恐怕我不同意。我的问题是,为什么要强制转换以及指导我们强制转换或不要投。我认为背后的逻辑可能是相同的,但概念完全不同。在他的问题中,他对(坚持不使用动态投射)使用[=表示怀疑39=] 和 static_cast。我的怀疑比他的还差一些。

好吧,编译器知道指向 C 的指针可以像继承的 class AB 一样被引用 - 所以强制转换 upAB 可以隐式完成。换句话说,编译器不知道指针是指向 C 的对象。它可能是一个不同的 class,它也继承了 A。通过添加演员表,您实际上是在说“不用担心编译器 - 我知道它实际上是 C 类型的 class”。

你的情况很简单。您尝试将指向 class B 对象的指针分配给指向 class C.

对象的指针

本身,你不能那样做,因为 class C 的对象也提供 class A 的功能,class 的对象B 没有。因此,使用 class B 的对象,而预期对象 C 是未定义的,因为 B 无法提供 C 的所有内容。

它与我们知道对象具有的类型有关。每个 C 也是一个 B,因此转换总是有效(隐式)。

每个 B 都不是 C 的一部分,因此您必须告诉编译器您确定该特定转换会起作用。那就是显式转换的使用。

The rules关于非基本类型允许的隐式转换如下:

  • Null pointers can be converted to pointers of any type
  • Pointers to any type can be converted to void pointers.
  • Pointer upcast: pointers to a derived class can be converted to a pointer of an accessible and unambiguous base class, without modifying its const or volatile qualification.

因此,当 C* 向上转换 B* 时,不需要显式转换。但是因为从 B*C* 的转换是一个指针 downcast 可以使用 C 样式转换,但首选以下之一:

  • dynamic_cast 可以使用,因为表达式是 B* 并且 new_type 是 C* 这个 运行-time 检查将被执行并且1:
  • 应该允许向下转换
  1. The most derived object pointed/identified by expression is examined. If, in that object, expression points/refers to a public base of Derived, and if only one subobject of Derived type is derived from the subobject pointed/identified by expression, then the result of the cast points/refers to that Derived subobject. (This is known as a "downcast".)
  2. Otherwise, if expression points/refers to a public base of the most derived object, and, simultaneously, the most derived object has an unambiguous public base class of type Derived, the result of the cast points/refers to that Derived (This is known as a "sidecast".)
  3. Otherwise, the runtime check fails. If the dynamic_cast is used on pointers, the null pointer value of type new_type is returned.
  • reinterpret_cast可以用,而且总是会成功。但是只有在给定 B 是 AliasedType 并且 C 是 DynamicType,满足这些条件之一的情况下,才定义它的结果的使用,2nd 项目符号允许沮丧:
  • AliasedType is (possibly cv-qualified) DynamicType
  • AliasedType and DynamicType are both (possibly multi-level, possibly cv-qualified at each level) pointers to the same type T
  • AliasedType is the (possibly cv-qualified) signed or unsigned variant of DynamicType
  • AliasedType is an aggregate type or a union type which holds one of the aforementioned types as an element or non-static member (including, recursively, elements of subaggregates and non-static data members of the contained unions): this makes it safe to obtain a usable pointer to a struct or union given a pointer to its non-static member or element.
  • AliasedType is a (possibly cv-qualified) base class of DynamicType
  • AliasedType is char or unsigned char: this permits examination of the object representation of any object as an array of unsigned char.
  • 也可以使用,当且仅当 已知 B* 实际上是多态寻址一个 C 对象。如果不是这种情况并且尝试 static_cast,将导致未定义的行为。