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/