您的位置:首页 > 编程语言 > C语言/C++

【c++内存分布系列】单继承

2013-09-06 15:37 309 查看
  父类包括成员函数、静态函数、静态方法,子类包括成员函数、静态函数、静态方法的情况与一个类时完全一致,这里就不做分析了。子类单独包含虚函数时继承无关,也不做分析了。

  一、父类子类都为空

#include <cstdio>

class A
{

};

class B: public A
{

};

int main(int argc, char** argv)
{
printf("%d\n", sizeof(B));
}


  windows输出:


1


  和一个空类时情况一致。

  二、父类包含成员变量、子类包含成员变量或子类父类都包含成员变量

#include <cstdio>

class A
{
public:
int a;
};

class B: public A
{

};

class AA
{

};

class BB: public AA
{
public:
int b;
};

class AAA
{
public:
int a;
};

class BBB: public AAA
{
public:
int b;
};

int main(int argc, char** argv)
{
printf("%d\n", sizeof(B));
printf("%d\n", sizeof(BB));
printf("%d\n", sizeof(BBB));
}


  windows输出:


4
4
8


  内存为成员变量,包括父类的。

  三、父类包含虚函数,子类未实现该函数

#include <cstdio>

class A
{
public:
int a;
virtual void vfun(){};
};

class B: public A
{

};

int main(int argc, char** argv)
{
printf("%d\n", sizeof(B));

B b;
b.a = 0xaaaaaaaa;
B* pb = &b;
printf("%08x\n", pb);
}


  windows输出:


8
003ffe40


  查看对象b的内存:


003FFE40 4C
003FFE41 57
003FFE42 22 00
003FFE44 AA
003FFE45 AA
003FFE46 AA
003FFE47 AA


  查看虚表0x0022574c:


B::`vftable':
0022574C 22 11
0022574E 22 00
00225750 00 00
00225752 00 00


  查看虚表指向的地址:


A::vfun:
00221122 E9 19 04 00 00 jmp A::vfun (221540h)



7: virtual void vfun(){};
00221540 55 push ebp
00221541 8B EC mov ebp,esp
00221543 81 EC CC 00 00 00 sub esp,0CCh


  可知b.vfun()执行的是a的虚函数。

  四、父类包含虚函数、子类实现该函数

#include <cstdio>

class A
{
public:
int a;
virtual void vfun(){};
};

class B: public A
{
public:
void vfun(){};
};

int main(int argc, char** argv)
{
printf("%d\n", sizeof(B));

B b;
b.a = 0xaaaaaaaa;
B* pb = &b;
printf("%08x\n", pb);
}


  windows输出:


8
002bfc10


  查看对象b地址内容:


002BFC10 4C
002BFC11 57
002BFC12 E7 00
002BFC14 AA
002BFC15 AA
002BFC16 AA
002BFC17 AA


  查看虚表0x00e7574c:


B::`vftable':
00E7574C 27
00E7574D 11 E7
00E7574F 00 00


  查看该续表中的指针0x00e71127:


B::vfun:
00E71127 E9 24 04 00 00 jmp B::vfun (0E71550h)



10: class B: public A
11: {
12: public:
13: void vfun(){};
00E71550 55 push ebp
00E71551 8B EC mov ebp,esp
00E71553 81 EC CC 00 00 00 sub esp,0CCh


  可知该虚表指向类B中的实现。

  五、虚继承父类,子类为空

#include <cstdio>

class A
{
public:
int a;
};

class B: virtual public A
{
public:
};

int main(int argc, char** argv)
{
printf("%d\n", sizeof(B));

B b;
b.a = 0xaaaaaaaa;
B* pb = &b;
printf("%08x\n", pb);
}


  windows输出:


8
0036f810


  查看对象b内存:


0036F810 48
0036F811 57
0036F812 34 01
0036F814 AA
0036F815 AA
0036F816 AA
0036F817 AA


  内存中多了0x01345748,这个是虚基类表的指针,作用于虚函数表类似后面会详细讲。查看该虚基类表:


B::`vbtable':
01345748 00 00
0134574A 00 00
0134574c 04 00
0134574e 00 00


  虚基类表内容含义后面讲。

  六、虚继承父类包含虚函数

#include <cstdio>

class A
{
public:
int a;
virtual void vfun(){};
};

class B: virtual public A
{
public:
};

int main(int argc, char** argv)
{
printf("%d\n", sizeof(B));

B b;
b.a = 0xaaaaaaaa;
B* pb = &b;
printf("%08x\n", pb);
}


  windows输出:


12
002efa64


  可见内存又增加了4字节。看下对象b内存:


002EFA64 54
002EFA65 57
002EFA66 86 00
002EFA68 4C
002EFA69 57
002EFA6A 86 00
002EFA6C AA
002EFA6D AA
002EFA6E AA
002EFA6F AA


  有两个指针,分别为虚基类表和虚函数表:


B::`vftable':
0086574C 22 11
0086574E 86 00
00865750 00 00
00865752 00 00
B::`vbtable':
00865754 00 00
00865756 00 00


  此例中子类未实现虚函数。子类实现虚函数与四类似,只是这里多了个虚基类表,就不详细讲了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: