深入理解C++多态

面试必问题:c++如何实现多态。
C++多态实现方式:
基类定义虚函数,子类继承基类,并重写虚函数。虚函数放在虚函数表,类对象都有一个虚函数指针指向虚函数表。虚函数表真正的函数地址和虚函数指针都是在构造函数中进行初始化的。即子类重写基类的虚函数后,子类的虚函数表中保存的地址是子类的虚函数地址。子类对象的虚函数指针在构造函数中初始化,指向子类自己的虚函数表。

1、对象的静态类型:对象在声明时采用的类型。是在编译期确定的。
2、对象的动态类型:目前所指对象的类型。是在运行期决定的。对象的动态类型可以更改,但是静态类型无法更改
3、静态绑定:绑定的是对象的静态类型,某特性(比如函数)依赖于对象的静态类型,发生在编译期。
4、动态绑定:绑定的是对象的动态类型,某特性(比如函数)依赖于对象的动态类型,发生在运行期。
动态绑定:
基类的指针或者引用指向子类的对象,在调用虚函数时,调用的是子类重写的虚函数。编译期并不知道真正调用的函数地址,需要到运行期依赖于指向的对象。为了更好的理解。下面看代码。
dosomething()不是虚函数,所以在编译期就能确定调用函数地址。 fun()是虚函数,需要动态绑定,可以见汇编代码,call命令的操作数是eax,依赖于指针指向的对象。

c++源码:

class Base
{
public:
void dosomething()
{
cout << "base dosome thing" << endl;
}
virtual void fun()
{
cout << "hello base" << endl;
}
};

class Derive:public Base
{
public:
void dosomething()
{
cout << "derive dosome thing" << endl;
}
virtual void fun()
{
cout << "hello Derive" << endl;
}
};


int main()
{
Derive *pd = new Derive;
Base *pa = pd;
pd->fun();
pa->fun();

pd->dosomething();
pa->dosomething();
system("pause");
return 0;
}


; 38 : {

push ebp
mov ebp, esp
sub esp, 232 ; 000000e8H
push ebx
push esi
push edi
lea edi, DWORD PTR [ebp-232]
mov ecx, 58 ; 0000003aH
mov eax, -858993460 ; ccccccccH
rep stosd

; 39 : Derive *pd = new Derive;

push 4
call ??2@YAPAXI@Z ; operator new
add esp, 4
mov DWORD PTR $T1[ebp], eax
cmp DWORD PTR $T1[ebp], 0
je SHORT $LN3@main
mov ecx, DWORD PTR $T1[ebp]
call ??0Derive@@QAE@XZ
mov DWORD PTR tv72[ebp], eax
jmp SHORT $LN4@main
$LN3@main:
mov DWORD PTR tv72[ebp], 0
$LN4@main:
mov eax, DWORD PTR tv72[ebp]
mov DWORD PTR _pd$[ebp], eax

; 40 : Base *pa = pd;

mov eax, DWORD PTR _pd$[ebp]
mov DWORD PTR _pa$[ebp], eax

; 41 : pd->fun();

mov eax, DWORD PTR _pd$[ebp]
mov edx, DWORD PTR [eax]
mov esi, esp
mov ecx, DWORD PTR _pd$[ebp]
mov eax, DWORD PTR [edx]
call eax
cmp esi, esp
call __RTC_CheckEsp

; 42 : pa->fun();

mov eax, DWORD PTR _pa$[ebp]
mov edx, DWORD PTR [eax]
mov esi, esp
mov ecx, DWORD PTR _pa$[ebp]
mov eax, DWORD PTR [edx]
call eax ;动态绑定的结果,编译期还不确定还是地址
cmp esi, esp
call __RTC_CheckEsp

; 43 :
; 44 : pd->dosomething();
;静态绑定,编译就确定了调用函数地址
mov ecx, DWORD PTR _pd$[ebp]
call ?dosomething@Derive@@QAEXXZ ; Derive::dosomething

; 45 : pa->dosomething();

mov ecx, DWORD PTR _pa$[ebp]
call ?dosomething@Base@@QAEXXZ ; Base::dosomething


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值