class Parent {
public:
    void sleep() {cout<<"Paren::sleep";}
};

class Child: public Parent {
public:
    void gotoSchool(){cout<<"chil::gotoSchool";}
};


int main( )
{
  Parent parent;
  Child child;

  // upcast - implicit type cast allowed
  Parent *pParent = &child;  //OK.

  // downcast - explicit type case required
  Child *pChild =  (Child *) &parent; //OK due to typecast but not safe when we call child specific method

  pParent -> sleep();
  pChild -> gotoSchool(); //Undefined but works ok on VS08

  return 0;
}

问题:

在上面的代码中 pChild -> gotoSchool(); 按照标准未定义。使用 undefined 一词,这意味着它可能有效,也可能无效。它对我有用。但我的问题是为什么它有效?它不应该有。我无法在内存中可视化布局对象。

//Parent 对象甚至对 gotoSchool 方法一无所知,为什么指向 Parent 对象的指针仍然打印 gotoSchool。这里的问题不是关于未定义的行为,而是关于它如何知道
gotoSchool 方法,所以 即使靠运气 它也不应该调用 gotoSchool 方法来打印 Child::gotoSchool。
Parent         Child
-----------     -------------
|         |     |           |
|  sleep  |     |   sleep   |
|         |     | gotoSchool|
-----------     -------------

当然,对象内部不包含成员函数,而只包含数据成员。上图仅供说明。

最佳答案



因为您的编译器的实现方式恰好导致了这种行为。



如果您的意思是编译器不应该允许这种行为,那么……标准不需要那样做。

它可能,它可以,而且确实如此。



我手头没有 Visual Studio 的源代码,所以我不能确切地告诉你它是如何工作的。但一般来说,成员函数是作为常规函数实现的,除了一个包含对象地址的额外参数。函数本身在内存中的位置与对象的内存无关。编译器确切地知道函数的代码在哪里。

您甚至可以执行 ((Child*)nullptr)->gotoSchool(); 并观察相同(未定义)的行为。

没有明显的原因为什么它不能具有观察到的行为。



对象的内存布局与函数无关,因为函数从不使用对象的任何内存。

关于c++ - 在 C++ 中向下转换期间的内存布局,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/33108154/

10-10 09:40