【问题标题】:Downcasting in oops哎呀,垂头丧气
【发布时间】:2019-02-13 07:07:51
【问题描述】:
class Parent
{};
class A_child : public Parent
{
  void A_method();
};
class B_child : public Parent
{
  void B_method();
};
void main()
{
  A_child a;
  Parent *p = &a;
  B_child *b = (B_child*)&p;
  b->B_method();
}

这段代码是用 C++ 编写的。这是一个逻辑错误,因为我们试图将“猫”变成“狗”。但它有效。谁能解释为什么以及如何?

【问题讨论】:

  • 这是未定义的行为。它不工作,它只是不会崩溃。
  • B_child 中添加一个int,将其设置为B_method 中的某个值,然后看看效果如何。
  • @tkausl - 我不明白。你的意思是说这段代码行不通?
  • (B_child*) 是 C 风格的演员表。是神锤。使用 C 型铸件,您可以将圆形钉子强制插入方孔。无论想法多么糟糕,它都会使 A 适合 B。避免 C 风格的强制转换。在此处使用dynamic_cast 并注意返回的空指针。
  • 一切都与记忆有关。 A_childB_child 具有相同的结构,因此适合内存中的相同模式。通过使用 C 风格的类,您只是将b 指向a 的内存地址(通过p)。因为记忆模式是相同的,所以它是偶然的。但是,正如其他人指出的那样,如果尽管从相同的基类继承,但结构不同的类,它们在内存中的布局会有所不同,并且 C 风格的强制转换将是未定义的行为。 @zzxyz 建议添加一个int 来“扰乱”b 的内存模式并导致失败。

标签: c++ oop downcast


【解决方案1】:

可能但不能保证不会导致错误,因为您的 B_method 有效 static

  1. 可以在不取消引用类指针的情况下查找和调用该方法
  2. 方法本身不需要取消引用类指针。

只要方法变成virtual(现在需要类指针来访问vtable来查找函数地址),访问类数据,或者你打喷嚏或看编译器好笑,你就会处理未绑定的内存访问。

我要强调的是,虽然假设的编译器不需要取消引用类指针,但它是允许的,并且任何特定的编译器实现都可能需要

进一步阅读...查看接受的答案Difference between Object and instance : C++ 在您访问与类的特定实例关联的instance data 之前,您的类指针不太可能被查看。

或者……另一种说法。如果您可以在函数声明前添加static,则使用无效指针调用它可能会起作用。

另见:

class MyClass
{
public:
  int doSomething(int x)
  {
    printf("%d", x);
    return x;
  }
};

int main()
{
  MyClass *pMyClass = nullptr;
  pMyClass->doSomething(42);
}

【讨论】:

    【解决方案2】:

    谁能解释为什么以及如何?

    ParentB_child 的基础,因此从Parent *p 类型到B_child* 的转换是正确的。但是,只有当p 确实指向B_child 实例的基本子对象时,才定义通过此转换后的指针访问指向对象的行为。

    前提条件不成立,因此程序的行为未定义。可能的行为包括,但都不能保证:

     - working
     - not working
     - random output
     - non-random output
     - the expected output
     - unexpected output
     - no output
     - any output
     - crashing at random
     - crashing always
     - not crashing at all
     - corruption of data
     - different behaviour, when executed on another system
     -                    , when compiled with another compiler
     -                    , on tuesday
     -                    , only when you are not looking
     - same behaviour in any or all of the above cases
     - anything else within the power of the computer (hopefully limited by the OS)
    

    永远不要 static_castreinterpret_cast 或 C 样式将表达式转换为另一种类型,除非 可以证明转换是正确的。如果您不确定,可以使用dynamic_cast

    【讨论】:

      猜你喜欢
      • 2010-12-04
      • 2018-10-31
      • 1970-01-01
      • 2021-12-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-23
      • 1970-01-01
      相关资源
      最近更新 更多