设为首页 加入收藏

TOP

c++ 对象的内存布局(一)
2015-07-20 17:35:29 来源: 作者: 【 】 浏览:8
Tags:对象 内存 布局
对象的影响因素
?
简而言之,一个类可能会有如下的影响因素:
1)成员变量
2)虚函数(产生虚函数表)
3)单一继承(只继承于一个类)
4)多重继承(继承多个类)
5)重复继承(继承的多个父类中其父类有相同的超类)
6)虚拟继承(使用virtual方式继承,为了保证继承后父类的内存布局只会存在一份)
上述的东西通常是C++这门语言在语义方面对对象内部的影响因素,当然,还会有编译器的影响(比如优化),还有字节对齐的影响。在这里我们都不讨论,我们只讨论C++语言上的影响。
?
本篇文章着重讨论下述几个情况下的C++对象的内存布局情况。
?
1)单一的一般继承(带成员变量、虚函数、虚函数覆盖)
2)单一的虚拟继承(带成员变量、虚函数、虚函数覆盖)
3)多重继承(带成员变量、虚函数、虚函数覆盖)
4)重复多重继承(带成员变量、虚函数、虚函数覆盖)
5)钻石型的虚拟多重继承(带成员变量、虚函数、虚函数覆盖)
?
(1)单一的一般继承
下面,我们假设有如下所示的一个继承关系:
?
?
?
请注意,在这个继承关系中,父类,子类,孙子类都有自己的一个成员变量。而了类覆盖了父类的f()方法,孙子类覆盖了子类的g_child()及其超类的f()。
?
?
?
可见以下几个方面:
1)虚函数表在最前面的位置。
2)成员变量根据其继承和声明顺序依次放在后面。
3)在单一的继承中,被override的虚函数在虚函数表中得到了更新。(Child的f覆盖Parent的f函数,然后GrandChild的f覆盖Child的f;GrandChild的g_child覆盖Child的g_child)
?
?代码验证如下
?
?
?
/*
version: 1.0
author: hellogiser
blog: http://www.cnblogs.com/hellogiser
date: 2014/9/29
*/
?
#include "stdafx.h"
#include
using namespace std;
?
class Parent
{
public:
? ? int iparent;
? ? Parent (): iparent (10) {}
? ? virtual void f()
? ? {
? ? ? ? cout << " Parent::f()" << endl;
? ? }
? ? virtual void g()
? ? {
? ? ? ? cout << " Parent::g()" << endl;
? ? }
? ? virtual void h()
? ? {
? ? ? ? cout << " Parent::h()" << endl;
? ? }
?
};
?
class Child : public Parent
{
public:
? ? int ichild;
? ? Child(): ichild(100) {}
? ? virtual void f()
? ? {
? ? ? ? cout << "Child::f()" << endl;
? ? }
? ? virtual void g_child()
? ? {
? ? ? ? cout << "Child::g_child()" << endl;
? ? }
? ? virtual void h_child()
? ? {
? ? ? ? cout << "Child::h_child()" << endl;
? ? }
};
?
class GrandChild : public Child
{
public:
? ? int igrandchild;
? ? GrandChild(): igrandchild(1000) {}
? ? virtual void f()
? ? {
? ? ? ? cout << "GrandChild::f()" << endl;
? ? }
? ? virtual void g_child()
? ? {
? ? ? ? cout << "GrandChild::g_child()" << endl;
? ? }
? ? virtual void h_grandchild()
? ? {
? ? ? ? cout << "GrandChild::h_grandchild()" << endl;
? ? }
};
?
typedef void(*Fun)(void);
?
/*
vptr ? ? ? ---> Parent::f(),Parent::g(),Parent::h()
iparent
*/
void test_parent()
{
? ? Parent obj;
? ? Fun pFun;
? ? int **pVtab = (int **)(&obj);
?
? ? int n = 3;
? ? cout << "[0] Parent::_vptr->" << endl;
? ? for (int i = 0; i < n; i++)
? ? {
? ? ? ? pFun = (Fun)pVtab[0][i];
? ? ? ? cout << "------[" << i << "] ";
? ? ? ? pFun();
? ? }
? ? cout << "[1] Parent.iparent = " << (int)pVtab[1] << endl;
? ? cout << "============================================" << endl;
}
?
/*
vptr ? ? ? ---> Child::f(),Parent::g(),Parent::h(),Child::g_child(),Child::h_child()
iparent
ichild
*/
void test_child()
{
? ? Child obj;
? ? Fun pFun;
? ? int **pVtab = (int **)(&obj);
?
? ? int n = 5;
? ? cout << "[0] Child::_vptr->" << endl;
? ? for (int i = 0; i < n; i++)
? ? {
? ? ? ? pFun = (Fun)pVtab[0][i];
? ? ? ? cout << "------[" << i << "] ";
? ? ? ? pFun();
? ? }
? ? cout << "[1] Parent.iparent = " << (int)pVtab[1] << endl;
? ? cout << "[2] Child.ichild = " << (int)pVtab[2] << endl;
? ? //cout << "[3] GrandChild.igrandchild = " << (int)pVtab[3] << endl;
? ? cout << "============================================" << endl;
}
?
?
/*
vptr ? ? ? ---> GrandChild::f(),Parent::g(),Parent::h(),GrandChild::g_child(),Child::h_child()
iparent
ichild
igrandchild
*/
void test_grandchild()
{
? ? GrandChild obj;
? ? Fun pFun;
? ? int **pVtab = (int **)(&obj);
?
? ? int n = 5;
? ? cout << "[0] GrandChild::_vptr->" << endl;
? ? for (int i = 0; i < n; i++)
? ? {
? ? ? ? pFun = (Fun)pVtab[0][i];
? ? ? ? cout << "------[" << i << "] ";
? ? ? ? pFun();
? ? }
? ? cout << "[1] Parent.iparent = " << (int)pVtab[1] << endl;
? ? cout << "[2] Child.ichild = " << (int)pVtab[2] << endl;
? ? cout << "[3] GrandChild.igrandchild = " << (int)pVtab[3] << endl;
? ? cout << "============================================" << endl;
}
?
int main()
{
? ? test_parent();
? ? test_child();
? ? test_grandchild();
? ? return 0;
}
/*
[0] Parent::_vptr->
------[0] ?Parent::f()
------[1] ?Parent::g()
------[2] ?Parent::h()
[1] Parent.iparent = 10
============================================
[0] Child::_vptr->
------[0] Child::f()
------[1] ?Parent::g()
------[2] ?Parent::h()
首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇poj2728 Desert King,最优比例生.. 下一篇C++哪些运算符重载可以重载?

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·有没有适合新手练习 (2025-12-26 01:48:47)
·用清华镜像网怎么下 (2025-12-26 01:48:44)
·请比较Python和R语言 (2025-12-26 01:48:42)
·JAVA现在的就业环境 (2025-12-26 01:19:24)
·最好的java反编译工 (2025-12-26 01:19:21)