快速业务通道

细谈C++多态性的“动”与“静”

作者 佚名技术 来源 程序设计 浏览 发布时间 2012-06-29

在我们讨论多态的时候,先看看什么是硬编码和软编码:硬编码就是把代码写死了,导致弹性不足,降低了可扩展性,例如在代码里的if……else……;switch……case……

这些代码通常都属于硬编码,项目中的这些代码多了,就相当于说明这个代码的灵活性、扩展性、弹性等等的少了。

所以,我们要尽量使用软编码,通俗点就是“别把话说死了,留点转弯的余地”。多态性就是这种软编码特性的反映,下面我们一起来研究一下多态性。

多态性是一种抽象,把事物的特征抽象出来,然后事物的具体形态我们就不关心了。

例如对工人这种事物来说,他的特征就是工作,至于是什么工人,他做什么工作,我们就不用关心了,只要我们以“工人。工作”这种方式去调用。那他就会为我们工作了。

那为什么我们不抽象出其他的特征,只抽象出工作这个特征呢?因为我们只对这个特征感兴趣,他的什么吃饭、睡觉、如厕等的特性我们都不关心了。有了多态,我们就可以实现软编码了!

讲解了多态的概念之后,我们来看看多态的实现(C++的实现):

多态的实现是通过虚函数表(VTable),每个类如果有虚函数,那它就有一个虚函数表,所有的对象都共享这一个VTable.这个概念也叫做动态联编,还有静态联编,这些概念都是通过在程序执行的时候表现出来的性质来定的,我们下面会看看它的“动”和“静”究竟体现在哪里。

先看一段代码:

class C0
...{
public:
void Test()
...{
cout << "call C0 Test()。" << endl;
}
};

这个类没有虚函数,调用的时候就是静态调用。调用的代码如下:

// 静态编译(早绑定 early binding)
C0 *pO0;
C0 obj0;
pO0 = &obj0;
pO0->Test();
它的反汇编代码如下:
// 直接调用函数(已经知道地址)
00401432 mov ecx,dWord ptr [ebp-0Ch]
00401435 call @ILT+160(C0::Test) (004010a5)

下面看看带虚函数的类:

class C1
...{
public:
virtual void Test()
...{
cout << "call C1 Test()" << endl;
}
};
class C11 : public C1
...{
public:
void Test()
...{
cout << "call C11 Test()" << endl;
}
};

它的调用:

C11 obj11;
C1 *pObj1;
pObj1 = &obj11;
// 这里生成的汇编代码
// 0040144A lea edx,[ebp-14h] // 寻址找到pObj1
// 0040144D mov dword ptr [ebp-1Ch],edx
pObj1->Test();
// 这里生成的汇编代码
// 00401450 mov eax,dword ptr [ebp-1Ch] // 取得虚表地址
// 00401453 mov edx,dword ptr [eax]
// 00401455 mov esi,esp
// 00401457 mov ecx,dword ptr [ebp-1Ch] //
根据虚表的位置来取得Test()函数
// 0040145A call dword ptr [edx] // 调用Test()函数

根据上述的汇编代码,我们可以知道,在多态调用函数的时候,程序执行以下步骤:

1、寻址找到pObj1

2、由于C11重载了Test虚函数,所以*pObj1指向的就是C11的VTable的地址

3、调用pObj1->Test()时,程序通过Vptr(虚表的指针,对象的首地址),找到VTable,再根据偏移调用Test函数。

由于上述的多态调用过程是一个动态的过程(在运行时去“找”函数来调用),而不是编译完就直接把函数地址摆在那里了,所以被称作“动态联编”。

上面把多态的“动”和“静”的特点结合代码说了一遍,希望能说清楚了。

下面再验证一个类的虚表的问题,如果你对虚表已经很熟悉了,就不用再往下看了。

在很多书上都已经说明了C++的对象模型,这里只是做个验证。看看这段代码:

class C1
...{
public:
virtual void Test()
...{
cout << "call C1 Test()&quo

凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

分享到: 更多

Copyright ©1999-2011 厦门凌众科技有限公司 厦门优通互联科技开发有限公司 All rights reserved

地址(ADD):厦门软件园二期望海路63号701E(东南融通旁) 邮编(ZIP):361008

电话:0592-5908028 传真:0592-5908039 咨询信箱:web@lingzhong.cn 咨询OICQ:173723134

《中华人民共和国增值电信业务经营许可证》闽B2-20100024  ICP备案:闽ICP备05037997号