这道题解题的关键在于了解类存分配机制以及虚函数的在类中的存储 . 需要明白的几个机制: 1. I386 的 cpu 采用小端机制,小端的 cpu 存储 0x12345678" name="description" />
MILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">这道题解题的关键在于了解类存分配机制以及虚函数的在类中的存储.
1. I386的cpu采用小端机制,小端的cpu存储0x12345678时看起来会是 78 56 34 12 ,看起来有点费劲。
2. I386的堆栈是由高往低生长的,也即堆栈地址寄存器是自减的。在函数体内,先定义的变量将在高地址位,后定义的变量在低地址位。
中软一道面试题的解析
题目如下
#include "stdafx.h"
class A
{
public:
virtual void fun();
};
void A::fun()
{
printf("output A");
return;
}
class B : A
{
public:
virtual void fun();//此处定义了虚函数,比较关键
B(int,char);
int a;
char b;
void funtion(){}
};
B::B(int a1,char b1)
{
a = a1;
b = b1;
}
void B::fun()
{
printf("output B");
return;
}
int main()
{
B test(257,'y');
B *p;
p = &test;
char ch = *((char *)p + 5);
printf("%c\n",ch);
int size_B = sizeof(B);
printf("%d\n",size_B);
return 0;
}
这道题解题的关键在于了解类存分配机制以及虚函数的在类中的存储.
1. I386的cpu采用小端机制,小端的cpu存储0x12345678时看起来会是 78 56 34 12 ,看起来有点费劲。
2. I386的堆栈是由高往低生长的,也即堆栈地址寄存器是自减的。在函数体内,先定义的变量将在高地址位,后定义的变量在低地址位。
内存块模拟:
地址 | 指针P内存位置 | clearcase/" target="_blank" >cccccc; PADDING-BOTTOM: 0cm; BORDER-LEFT: #d4d0c8; WIDTH: 427.55pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 0.5pt solid; HEIGHT: 15.3pt; mso-border-left-alt: solid windowtext .5pt" valign="top" width="570" colspan="12"> Class B的实例test占用的内存图 | ||||||||||||||
地址 | 0x04 | 0x05 | 0x06 | 0x07 | 0x08 | 0x09 | 0x0a | 0x0b | 0x0c | 0x0d | 0x0e | 0x0f | 0x10 | 0x11 | 0x12 | 0x13 |
变量 |
|
|
|
| 虚函数地址 | Test.b | Test.a |
|
|
| ||||||
内存 | 0x08 | 0x00 | 0x00 | 0x00 | Ff | 78 | 98 | 00 | 01 | 01 | 00 | 00 | 79 | Cc | Cc | Cc |
从上图来分析,(char )p + 5 的即是 0x00000008+5*(sizeof(char)) = 0x0000000d, 而里面的值是0x01.故ch的值是 0x01
类里面的普通函数是不会影响类的大小的,即使类里有多个普通函数定义,用sizeof计算,它的大小都不会变化,但虚函数不同,定义在类里的虚函数需要占用4个字节,这四个字节是用来存放虚函数表的入口地址的,即使在类里定义了多个虚函数,同样也只需要4个字节。