2

我正在阅读“ Bjarne Stroustrup 的 C++ 多重继承,发表在 1999 年 5 月号的“C/C++ 用户期刊”上。以下摘录来自相同(第 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了无需显式转换即可完成。这绝对意味着强制转换是隐式处理的。然后,

  1. 为什么,当我们尝试pc = pb指针时,强制转换是必要的?
  2. 指导这一点的规则是什么,在哪里?
  3. 它与增量值递增/递减指针有关吗?

编辑

Jonathan Mee将此问题标记为“从父母到孩子要采用哪种类型的演员? ”的副本。我害怕,我不同意。我的问题是关于为什么要施放,以及这条指导我们施放或不施放的规则在哪里。我认为背后的逻辑可能相同,但概念完全不同。在他的问题中,他对(坚持不使用动态转换)使用 dynamic_cast 和 static_cast 持怀疑态度。我的怀疑比他还差一些。

4

4 回答 4

4

它与我们知道的对象具有的类型有关。EveryC也是 a B,因此转换始终有效(隐式)。

EveryB不是 a 的一部分C,因此您必须告诉编译器您肯定知道此特定转换将起作用。这就是显式演员表的使用。

于 2016-07-13T12:18:43.010 回答
3

允许对非基本类型进行隐式转换的规则如下:

  • 空指针可以转换为任何类型的指针
  • 指向任何类型的指针都可以转换为 void 指针。
  • 指针向上转换:指向派生类的指针可以转换为可访问且明确的基类的指针,而无需修改其constvolatile限定。

因此,当从 a向上C*转换为B*显式转换时,没有必要。但是因为从 aB*到 a的转换是向下转换C*的指针,所以可以使用 C 样式转换,但首选以下方法之一:

  • dynamic_cast可以使用,因为表达式是 aB*并且 new_type 是 aC*这个运行时检查将被执行并且向下转换应该被1允许:
  1. 检查表达式指向/标识的最派生对象。如果在该对象中,表达式指向/引用 Derived 的公共基,并且如果只有一个 Derived 类型的子对象是从表达式指向/标识的子对象派生的,则转换的结果指向/引用该 Derived 子对象。(这被称为“沮丧”。)
  2. 否则,如果表达式指向/引用最派生对象的公共基类,并且同时,最派生对象具有 Derived 类型的明确公共基类,则转换的结果指向/引用该派生对象(这是已知的作为“旁观者”。)
  3. 否则,运行时检查将失败。如果在指针上使用了 dynamic_cast,则返回 new_type 类型的空指针值。
  • reinterpret_cast可以使用,并且永远成功。B但是只有在给定的 AliasedType 和CDynamicType 满足这些条件之一的情况下才定义使用它的结果,第二个项目符号允许向下转换:
  • AliasedType 是(可能是 cv 限定的)DynamicType
  • AliasedType 和 DynamicType 都是指向同一类型 T
  • AliasedType 是 DynamicType 的(可能是 cv 限定的)有符号或无符号变体
  • AliasedType 是聚合类型或联合类型,它将上述类型之一作为元素或非静态成员(递归地包括子聚合的元素和所包含联合的非静态数据成员):这使得获取一个指向结构或联合的可用指针,给定一个指向其非静态成员或元素的指针。
  • AliasedType 是 DynamicType 的(可能是 cv 限定的)基类
  • AliasedType is charor unsigned char:这允许将任何对象的对象表示检查为无符号字符数组。
  • static_cast当且仅当已知B*实际上是对C对象进行多态寻址时,也可以使用。如果不是这种情况并static_cast尝试 a ,将导致未定义的行为。
于 2016-07-13T12:59:46.127 回答
1

好吧,编译器知道指向的指针C可以像继承的class Aor一样被引用B- 所以强制转换为orA可以B隐式完成。换一种方式,编译器不知道指针指向C. 它可能是一个不同的类,它也继承了A. 通过添加一个演员,你基本上是在说“别担心编译器——我知道它实际上是一个 C 类型的类”。

于 2016-07-13T12:16:43.253 回答
1

在你的情况下,这很简单。您尝试将指向类对象的指针分配给指向类对象的B指针C

本质上,你不能这样做,因为 class 的对象C也提供 class 的功能,而 class 的A对象B没有。因此,在期望对象的B地方使用类对象C是未定义的,因为B不能提供一切C

于 2016-07-13T12:17:09.720 回答