C++-C++子类对象的内存结构问题?
class Based
{
public:
Based(int n):num(n){}
private:
int num;
};
class Dervied : public Based
{
public:
Dervied(int n, int m):Based(n), mem(m){}
private:
double mem;
};
int main()
{
Dervied d(2, 3);
return 0;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
便于子类向基类转换时的内存截断,因为每个子类的大小是不确定的,如果把子类的部分放在前面,那么将子类转换成基类的时候直接按基类的大小进行内存截断就会出问题,要实现正确的截断的话就要用到别的机制了,比较复杂,所以把基类部分放在前面的话,可以直接按基类的大小进行截断,得到正确的结果!
这样设计很方便,当派生类的指针转成基类的指针时,不需要计算偏移量。直接使用就行了。
Derived *d = new Derived;
Based *b = d;
b和d的值是一样的。如果把基类的数据成员放在后面,那就要计算偏移量了。一上面的例子为例的话。
b的值是d的值加上double mem,8个字节的偏移量。
参考维基百科:
非POD类的内存布局没有被C++标准规定。例如,许多流行的C++编译器通过将父类的字段和子类的字段并置来实现单继承,但是这并不被标准所需求。这种布局的选择使得将父类的指针指向子类的操作是平凡的(trivial)。一个正确书写的C++程序在任何情况下都不应该对被继承字段的布局有任何假定。
http://zh.wikipedia.org/zh-cn/C%2B%2B%E7%B1%BB
这样做的原因是,既然派生类要保留基类的所有属性和行为,自然地,每个派生类的实例都包含了一份完整的基类实例数据。在D中,并不是说基类C的数据一定要放在D的数据之前,只不过这样放的话,能够保证D中的C对象地址,恰好是D对象地址的第一个字节。这种安排之下,有了派生类D的指针,要获得基类C的指针,就不必要计算偏移量了。几乎所有知名的C++厂商都采用这种内存安排(基类成员在前)。在单继承类层次下,每一个新的派生类都简单地把自己的成员变量添加到基类的成员变量之后。