這道題解題的關鍵在于了解類存分配機制以及虛函數的在類中的存儲 . 需要明白的幾個機制: 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個字節。
原文轉自:http://www.anti-gravitydesign.com