Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/125.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 何时以及如何决定是否使用石膏?_C++_Pointers_Casting_Language Design_Language Concepts - Fatal编程技术网

C++ 何时以及如何决定是否使用石膏?

C++ 何时以及如何决定是否使用石膏?,c++,pointers,casting,language-design,language-concepts,C++,Pointers,Casting,Language Design,Language Concepts,我正经历着,“”。以下摘录摘自同一页(第5/17页) 4.4铸造 显式和隐式强制转换还可能涉及使用增量修改指针值: 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: ca

我正经历着,“”。以下摘录摘自同一页(第5/17页)

4.4铸造

显式和隐式强制转换还可能涉及使用增量修改指针值:

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))
类{void f();}; 类B{int f();}; 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;//错误:cast needed编译器知道,指向
C
的指针可以被引用,就像继承的
class a
B
一样,因此可以隐式地进行
a
B
的转换。相反,编译器不知道指针指向
C
的对象。它可能是另一个类,也继承了
a
。通过添加cast,您实际上是在说“别担心编译器-我知道它实际上是一个C类型的类”。

在您的例子中,它非常简单。您试图将指向类
B
对象的指针指定给指向类
C
对象的指针


就其本身而言,您无法做到这一点,因为类
C
的对象还提供类
A
的功能,而类
B
的对象不提供这些功能。因此,在预期对象
C
的情况下使用
B
类的对象是未定义的,因为
B
不能提供
C
所拥有的一切。

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

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

关于非基本类型允许的隐式转换,如下所示:

  • 空指针可以转换为任何类型的指针
  • 指向任何类型的指针都可以转换为空指针
  • 指针向上转换:指向派生类的指针可以转换为可访问且明确的基类指针,而无需修改其
    const
    volatile
    限定
因此,当从a
C*
向上转换到a
B*
时,不需要显式转换。但是,由于从a
B*
到a
C*
的转换是指针向下转换,因此可以使用C型转换,但最好使用以下方式之一:

  • 如果表达式为a
    B*
    且新类型为a
    C*
    ,则可以使用此选项。将执行此运行时检查,并且1应允许向下广播:
  • 检查表达式指向/标识的最派生对象。如果在该对象中,表达式指向/引用派生类型的公共基,并且如果只有一个派生类型的子对象是从表达式指向/标识的子对象派生的,则强制转换的结果指向/引用该派生子对象。(这被称为“沮丧”。)
  • 否则,如果表达式指向/引用最派生对象的公共基类,同时,最派生对象具有派生类型的明确公共基类,则强制转换的结果指向/引用该派生对象(这称为“侧转换”)
  • 否则,运行时检查将失败。如果在指针上使用动态\u转换,则返回new\u type类型的空指针值
    • 可以使用,并且将永远成功。但只有当
      B
      为AliasedType且
      C
      为DynamicType且满足以下条件之一时,才能定义其结果的使用,第二个项目符号允许向下投射:
    • AliasedType是(可能是cv限定的)DynamicType
    • AliasedType和DynamicType都是指向同一类型T的指针(可能是多级的,也可能是每个级别的cv限定)
    • AliasedType是DynamicType的有符号或无符号变体(可能是cv限定的)
    • AliasedType是一种聚合类型或联合类型,它将上述类型之一作为元素或非静态成员(递归地包括子聚合的元素和包含的联合的非静态数据成员)保存:这使得在给定指向结构或联合的非静态成员或元素的指针时,可以安全地获取指向该结构或联合的可用指针
    • AliasedType是DynamicType的基类(可能是cv限定的)
    • AliasedType是
      char
      unsigned char
      :这允许检查任何对象作为unsigned char数组的对象表示形式
    • 当且仅当已知
      B*
      实际上以多态方式寻址
      C
      对象时,也可以使用。如果情况并非如此,并且尝试执行
      静态\u cast
      ,则会导致未定义的行为

    在这里,你会有一个很好的解释:@JonathanMee的可能复制品-我的问题是,为什么要选演员,以及指导我们选演员还是不选演员的规则在哪里。我认为背后的逻辑可能是相同的,但概念是完全不同的。我的怀疑和你的怀疑没有任何相似之处,可以标记为重复。在你的问题中,你知道你为什么要铸造,但你对使用哪一个有疑问。我的怀疑仍然比你的要晚一些:)也许这超出了范围,但是当这样的角色(父->子)无效时,会发生什么行为呢?甜蜜而简单。我喜欢答案的“部分”。这无疑为隐式和显式转换扫清了很多障碍。
    因此**向下转换**到A或B可以隐式进行
    我不认为,你的意思是向下转换。不过,谢谢你的回答。抢手货改变了的,