![]() ![]() |
|
细谈C++多态性的“动”与“静” | |
作者:佚名 文章来源:不详 点击数 更新时间:2008/3/20 18:36:04 文章录入:杜斌 责任编辑:杜斌 | |
|
|
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()函数 |
|
![]() ![]() |