#include <iostream>
#include <stdio.h>
class Base
{
public:
virtual void function_1()
{
printf("Base function_1...\n");
}
virtual void function_2()
{
printf("Base function_2...\n");
}
virtual void function_3()
{
printf("Base function_3...\n");
}
};
class Sub : Base
{
public:
virtual void function_1()
{
printf("Sub function_1...\n");
}
virtual void function_2()
{
printf("Sub function_2...\n");
}
virtual void function_6()
{
printf("Sub function_6...\n");
}
};
int main(int argc, char ** argv)
{
Sub sub;
printf("sizeof = %ld\n", sizeof(class Base)); /* 4 */
printf("sizeof = %ld\n", sizeof(class Sub)); /* 4 */
printf("sub address is %x.\n", &sub); // this 指针,是堆栈里面的地址。虚表的地址不是this指针,是this指针的前四个字节。
printf("sub virtual table address is:%x\n", *(int*)&sub); // 虚表地址。取this指针的前4个字节。*(char*)&base为取一个字节。
typedef void(*pfunction)(void);
pfunction pf;
int temp = *((int*)(*(int*)&sub) + 0); // 取地址表里面的第一个值
// *(int*)&sub) 是虚表地址
// (int*) 转换成一个int*类型。
// *((int*)(*(int*)&sub) + 0), 加的是0,即取第一个4字节值。
pf = (pfunction)*((int*)(*(int*)&sub) + 0); // 或这样,取地址表里面的第一个值
pf(); // function_1
pf = (pfunction)*((int*)(*(int*)&sub) + 1); // 取第二个4字节值
pf(); // function_2
for (int i = 0; i < 4; i++) {
pf = (pfunction)*((int*)(*(int*)&sub) + i);
pf();
}
}
/*
sub:function_1
sub:function_2
base:function_3
sub:function_6
*/
#if 0
1.有重写关系。
sub对象
--------------- -----------------
| 0x123245 | ---------> | 0x123456 | sub:function_1
--------------- -----------------
| .... | | 0x123457 | sub:function_2
--------------- -----------------
| .... | | 0x123458 | Base:function_3
--------------- -----------------
| .... | | 0x123457 | Sub:function_6
--------------- -----------------
| .... | | 0x123457 |
--------------- -----------------
| 其它成员 | | 0x123457 |
--------------- -----------------
| .... | | 0x000000 |
--------------- -----------------
int main(int argc, char ** argv)
{
80486b0: 55 push %ebp
80486b1: 89 e5 mov %esp,%ebp
80486b3: 83 e4 f0 and $0xfffffff0,%esp
80486b6: 83 ec 20 sub $0x20,%esp
Sub sub;
80486b9: 8d 44 24 10 lea 0x10(%esp),%eax
80486bd: 89 04 24 mov %eax,(%esp)
80486c0: e8 a3 01 00 00 call 8048868 <_ZN3SubC1Ev>
printf("sizeof = %ld\n", sizeof(class Base)); /* 4 */
80486c5: c7 44 24 04 04 00 00 movl $0x4,0x4(%esp)
80486cc: 00
80486cd: c7 04 24 93 89 04 08 movl $0x8048993,(%esp)
80486d4: e8 a7 fe ff ff call 8048580 <printf@plt>
printf("sizeof = %ld\n", sizeof(class Sub)); /* 4 */
80486d9: c7 44 24 04 04 00 00 movl $0x4,0x4(%esp)
80486e0: 00
80486e1: c7 04 24 93 89 04 08 movl $0x8048993,(%esp)
80486e8: e8 93 fe ff ff call 8048580 <printf@plt>
printf("sub address is %x.\n", &sub); // this 指针,是堆栈里面的地址。虚表的地址不是this指针,是this指针的前四个字节。
80486ed: 8d 44 24 10 lea 0x10(%esp),%eax
80486f1: 89 44 24 04 mov %eax,0x4(%esp)
80486f5: c7 04 24 a1 89 04 08 movl $0x80489a1,(%esp)
80486fc: e8 7f fe ff ff call 8048580 <printf@plt>
printf("sub virtual table address is:%x\n", *(int*)&sub); // 虚表地址。取this指针的前4个字节。*(char*)&base为取一个字节。
8048701: 8d 44 24 10 lea 0x10(%esp),%eax
8048705: 8b 00 mov (%eax),%eax
8048707: 89 44 24 04 mov %eax,0x4(%esp)
804870b: c7 04 24 b8 89 04 08 movl $0x80489b8,(%esp)
8048712: e8 69 fe ff ff call 8048580 <printf@plt>
typedef void(*pfunction)(void);
pfunction pf;
int temp = *((int*)(*(int*)&sub) + 0); // 取地址表里面的第一个值
8048717: 8d 44 24 10 lea 0x10(%esp),%eax
804871b: 8b 00 mov (%eax),%eax
804871d: 8b 00 mov (%eax),%eax
804871f: 89 44 24 18 mov %eax,0x18(%esp)
// *(int*)&sub) 是虚表地址
// (int*) 转换成一个int*类型。
// *((int*)(*(int*)&sub) + 0), 加的是0,即取第一个4字节值。
pf = (pfunction)*((int*)(*(int*)&sub) + 0); // 或这样,取地址表里面的第一个值
8048723: 8d 44 24 10 lea 0x10(%esp),%eax
8048727: 8b 00 mov (%eax),%eax
8048729: 8b 00 mov (%eax),%eax
804872b: 89 44 24 14 mov %eax,0x14(%esp)
pf(); // function_1
804872f: 8b 44 24 14 mov 0x14(%esp),%eax
8048733: ff d0 call *%eax
pf = (pfunction)*((int*)(*(int*)&sub) + 1); // 取第二个4字节值
8048735: 8d 44 24 10 lea 0x10(%esp),%eax
8048739: 8b 00 mov (%eax),%eax
804873b: 83 c0 04 add $0x4,%eax
804873e: 8b 00 mov (%eax),%eax
8048740: 89 44 24 14 mov %eax,0x14(%esp)
pf(); // function_2
8048744: 8b 44 24 14 mov 0x14(%esp),%eax
8048748: ff d0 call *%eax
for (int i = 0; i < 4; i++) {
804874a: c7 44 24 1c 00 00 00 movl $0x0,0x1c(%esp)
8048751: 00
8048752: eb 24 jmp 8048778 <main+0xc8>
pf = (pfunction)*((int*)(*(int*)&sub) + i);
8048754: 8b 44 24 1c mov 0x1c(%esp),%eax
8048758: 8d 14 85 00 00 00 00 lea 0x0(,%eax,4),%edx
804875f: 8d 44 24 10 lea 0x10(%esp),%eax
8048763: 8b 00 mov (%eax),%eax
8048765: 01 d0 add %edx,%eax
8048767: 8b 00 mov (%eax),%eax
8048769: 89 44 24 14 mov %eax,0x14(%esp)
pf();
804876d: 8b 44 24 14 mov 0x14(%esp),%eax
8048771: ff d0 call *%eax
pf(); // function_1
pf = (pfunction)*((int*)(*(int*)&sub) + 1); // 取第二个4字节值
pf(); // function_2
for (int i = 0; i < 4; i++) {
8048773: 83 44 24 1c 01 addl $0x1,0x1c(%esp)
8048778: 83 7c 24 1c 03 cmpl $0x3,0x1c(%esp)
804877d: 7e d5 jle 8048754 <main+0xa4>
pf = (pfunction)*((int*)(*(int*)&sub) + i);
pf();
}
}
804877f: b8 00 00 00 00 mov $0x0,%eax
8048784: c9 leave
8048785: c3 ret
#endif