在oops中向下倾倒

问题描述 投票:0回答:2
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 ++编写的。这是一个逻辑错误,因为我们试图将“猫”变成“狗”。但它的确有效。谁能解释为什么以及如何解释?

c++ oop downcast
2个回答
5
投票

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

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


3
投票

这很可能但不能保证不会导致错误,因为你的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);
}
© www.soinside.com 2019 - 2024. All rights reserved.