反汇编 之 virtual-08 多继承有函数覆盖的特点

11 篇文章 0 订阅

#include
#include <stdio.h>

/*
* 多继承有函数覆盖的特点
*/

class Base1
{
public:
virtual void function_1()
{
printf("Base1 function_1… ");
}

virtual void function_2()
{
printf("Base1 function_2… ");
}

};

class Base2
{
public:
virtual void function_3()
{
printf("Base2 function_3… ");
}

virtual void function_4()
{
printf("Base2 function_4… ");
}

};

class Sub : Base1, Base2
{
public:
virtual void function_1()
{
printf("Sub function_1… ");
}

virtual void function_3()
{
printf("Sub function_3… ");
}

virtual void function_5()
{
printf("Sub function_5… ");
}
};

int main(int argc, char ** argv)
{
Sub sub;

printf("size = %d ", sizeof(class Sub)); // 8。 直接继承两个父类,所以有两个虚函数表

printf("sub address is %x. ", &sub); // this 指针,是堆栈里面的地址。虚表的地址不是this指针,是this指针的前四个字节。

/* 对象的前4字节是第一个Base1的虚表 */
printf("sub virtual table address is:%x ", *(int*)&sub);

typedef void(*pfunction)(void);

pfunction pf;

for (int i = 0; i < 4; i++) {
int temp = *((int*)(*(int*)&sub) + i);
if (temp == 0) {
break;
}

pf = (pfunction)temp;
pf();
}

/* 对象的第二个4字节是Base2的虚表 */
printf("sub virtual table address is:%x ", *(int*)((int)&sub+4));
pfunction pf2;

for (int k = 0; k < 2; k++) {
int temp = *((int*)(*(int*)((int)&sub+4)) + k);
pf2 = (pfunction)temp;
pf2();
}

return 0;
}

/*
Sub function_1
Base1 function_2
Sub function_5

Sub address
Sub function_3
Base2 function_4
*/

#if 0

1.覆盖的是哪个在哪个虚表里;

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 30 sub $0x30,%esp
Sub sub;
80486b9: 8d 44 24 10 lea 0x10(%esp),%eax
80486bd: 89 04 24 mov %eax,(%esp)
80486c0: e8 ef 01 00 00 call 80488b4 <_ZN3SubC1Ev>

printf("size = %d ", sizeof(class Sub)); // 8。 直接继承两个父类,所以有两个虚函数表
80486c5: c7 44 24 04 08 00 00 movl $0x8,0x4(%esp)
80486cc: 00
80486cd: c7 04 24 12 8a 04 08 movl $0x8048a12,(%esp)
80486d4: e8 a7 fe ff ff call 8048580 printf@plt

printf("sub address is %x. ", &sub); // this 指针,是堆栈里面的地址。虚表的地址不是this指针,是this指针的前四个字节。
80486d9: 8d 44 24 10 lea 0x10(%esp),%eax
80486dd: 89 44 24 04 mov %eax,0x4(%esp)
80486e1: c7 04 24 1d 8a 04 08 movl $0x8048a1d,(%esp)
80486e8: e8 93 fe ff ff call 8048580 printf@plt

/* 对象的前4字节是第一个Base1的虚表 */
printf("sub virtual table address is:%x ", *(int*)&sub);
80486ed: 8d 44 24 10 lea 0x10(%esp),%eax
80486f1: 8b 00 mov (%eax),%eax
80486f3: 89 44 24 04 mov %eax,0x4(%esp)
80486f7: c7 04 24 34 8a 04 08 movl $0x8048a34,(%esp)
80486fe: e8 7d fe ff ff call 8048580 printf@plt

typedef void(*pfunction)(void);

pfunction pf;

for (int i = 0; i < 4; i++) {
8048703: c7 44 24 2c 00 00 00 movl $0x0,0x2c(%esp)
804870a: 00
804870b: eb 35 jmp 8048742 <main+0x92>
int temp = *((int*)(*(int*)&sub) + i);
804870d: 8b 44 24 2c mov 0x2c(%esp),%eax
8048711: 8d 14 85 00 00 00 00 lea 0x0(,%eax,4),%edx
8048718: 8d 44 24 10 lea 0x10(%esp),%eax
804871c: 8b 00 mov (%eax),%eax
804871e: 01 d0 add %edx,%eax
8048720: 8b 00 mov (%eax),%eax
8048722: 89 44 24 24 mov %eax,0x24(%esp)
if (temp == 0) {
8048726: 83 7c 24 24 00 cmpl $0x0,0x24(%esp)
804872b: 75 02 jne 804872f <main+0x7f>
break;
804872d: eb 1a jmp 8048749 <main+0x99>
}

pf = (pfunction)temp;
804872f: 8b 44 24 24 mov 0x24(%esp),%eax
8048733: 89 44 24 20 mov %eax,0x20(%esp)
pf();
8048737: 8b 44 24 20 mov 0x20(%esp),%eax
804873b: ff d0 call *%eax

typedef void(*pfunction)(void);

pfunction pf;

for (int i = 0; i < 4; i++) {
804873d: 83 44 24 2c 01 addl $0x1,0x2c(%esp)
8048742: 83 7c 24 2c 03 cmpl $0x3,0x2c(%esp)
8048747: 7e c4 jle 804870d <main+0x5d>
pf = (pfunction)temp;
pf();
}

/* 对象的第二个4字节是Base2的虚表 */
printf("sub virtual table address is:%x ", *(int*)((int)&sub+4));
8048749: 8d 44 24 10 lea 0x10(%esp),%eax
804874d: 83 c0 04 add $0x4,%eax
8048750: 8b 00 mov (%eax),%eax
8048752: 89 44 24 04 mov %eax,0x4(%esp)
8048756: c7 04 24 34 8a 04 08 movl $0x8048a34,(%esp)
804875d: e8 1e fe ff ff call 8048580 printf@plt
pfunction pf2;

for (int k = 0; k < 2; k++) {
8048762: c7 44 24 28 00 00 00 movl $0x0,0x28(%esp)
8048769: 00
804876a: eb 2f jmp 804879b <main+0xeb>
int temp = *((int*)(*(int*)((int)&sub+4)) + k);
804876c: 8b 44 24 28 mov 0x28(%esp),%eax
8048770: 8d 14 85 00 00 00 00 lea 0x0(,%eax,4),%edx
8048777: 8d 44 24 10 lea 0x10(%esp),%eax
804877b: 83 c0 04 add $0x4,%eax
804877e: 8b 00 mov (%eax),%eax
8048780: 01 d0 add %edx,%eax
8048782: 8b 00 mov (%eax),%eax
8048784: 89 44 24 1c mov %eax,0x1c(%esp)
pf2 = (pfunction)temp;
8048788: 8b 44 24 1c mov 0x1c(%esp),%eax
804878c: 89 44 24 18 mov %eax,0x18(%esp)
pf2();
8048790: 8b 44 24 18 mov 0x18(%esp),%eax
8048794: ff d0 call *%eax

/* 对象的第二个4字节是Base2的虚表 */
printf("sub virtual table address is:%x ", *(int*)((int)&sub+4));
pfunction pf2;

for (int k = 0; k < 2; k++) {
8048796: 83 44 24 28 01 addl $0x1,0x28(%esp)
804879b: 83 7c 24 28 01 cmpl $0x1,0x28(%esp)
80487a0: 7e ca jle 804876c <main+0xbc>
int temp = *((int*)(*(int*)((int)&sub+4)) + k);
pf2 = (pfunction)temp;
pf2();
}

return 0;
80487a2: b8 00 00 00 00 mov $0x0,%eax
}
80487a7: c9 leave
80487a8: c3 ret

#endif

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值