何时以及如何决定使用演员表?

时间:2016-07-13 12:10:02

标签: c++ pointers casting language-design language-concepts

我正在经历“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可以在不明确强制转换的情况下完成。这肯定意味着隐式处理了转换。然后,

  1. 当我们尝试pc = pb指针时,为什么需要进行投射?
  2. 这条规则的目的是什么?
  3. 是否与指针递增/递减delta值有关?
  4. 修改

    Jonathan Mee将此问题标记为“What Type of Cast to Go from Parent to Child?”的副本。我很害怕,我不同意。我的问题是, 为什么要投射以及这条规则指示我们施放或不施放 。我认为背后的逻辑可能是相同的,但概念完全不同。在他的问题中,他怀疑(坚持不使用动态演员)使用dynamic_cast和static_cast。我的疑问仍然是他背后的一些步骤。

4 个答案:

答案 0 :(得分:3)

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

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

答案 1 :(得分:2)

关于非基本类型的允许隐式转换的

The rules如下:

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

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

    如果表达式为B*且new_type为C*,则可以使用
  • dynamic_cast,此次运行时检查将执行,并且 1 < /强>:
  
      
  1. 检查由表达式指向/标识的派生对象最多的对象。如果在该对象中,表达式指向/指向Derived的公共基础,并且如果只有一个派生类型的子对象是从由表达式指向/标识的子对象派生的,则转换结果/指向该派生子对象。 (这被称为&#34; downcast&#34;。)
  2.   
  3. 否则,如果表达式points /引用最派生对象的公共基础,并且同时,最派生的对象具有Derived类型的明确公共基类,则转换点的结果/指的是Derived(这被称为&#34; sidecast&#34;。)
  4.   
  5. 否则,运行时检查失败。如果在指针上使用dynamic_cast,则返回类型为new_type的空指针值。
  6.   
  • reinterpret_cast可以使用,并且将永远成功。但只有在给定B为AliasedType并且C为DynamicType时,满足其中一个条件,即2 nd 项目符号时,才会定义结果的使用允许垂头丧气:
  
      
  • AliasedType是(可能是cv限定的)DynamicType
  •   
  • AliasedType和DynamicType都是(可能是多级,可能是每个级别的cv限定)指向相同类型的指针T
  •   
  • AliasedType是DynamicType
  • 的(可能是cv限定的)有符号或无符号变体   
  • AliasedType是一种聚合类型或联合类型,它将上述类型之一保存为元素或非静态成员(包括,递归地,包含联合的子聚合和非静态数据成员的元素):这使得它在给定指向其非静态成员或元素的指针的情况下,可以安全地获取指向结构或联合的可用指针。
  •   
  • AliasedType是(可能是cv限定的)DynamicType
  • 的基类   
  • AliasedType为charunsigned char:这允许将任何对象的对象表示检查为unsigned char数组。
  •   
    当且仅当已知 B*实际上是多态地处理C对象时,也可以使用
  • static_cast。如果不是这种情况并且尝试static_cast,则会导致未定义的行为。

答案 2 :(得分:1)

好吧,编译器知道指向C的指针可以像继承的class AB那样被引用 - 所以将向上转换为{{1 }}或A可以隐式完成。另一方面,编译器不知道指针是B的对象。它可以是一个不同的类,也继承C。通过添加一个演员,你基本上是说&#34; 不要担心编译器 - 我知道它实际上是一个类型C &#34;。

答案 3 :(得分:1)

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

本身,你不能这样做,因为类C的对象也提供了类A的功能,类B的对象没有。因此,期望对象B的类C的对象的使用未定义,因为B无法提供C所拥有的所有内容。