向上映射andVirtual

王朝other·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

//取一个对象的地址(或指针或引用),并看作基类的地址,这被

称为向上映射,因为继承树是以基类为顶点的。

关键字:向上映射,早捆绑,晚捆绑

一 看以下程序

#include<iostream.h>

class jilei

{

public:

void Draw();

};

void jilei::Draw()

{

cout<<"基类Draw"<<endl;

}

class paishenglei:public jilei

{

public:

void Draw();

};

void paishenglei::Draw()

{

cout<<"派生类Draw"<<endl;

}

void Play(jilei &j)

{

j.Draw();

}

void main(void)

{

jilei jl;

paishenglei psl;

Play(jl);

Play(psl); //向上映射,但输出为“基类Draw”

}

过运行这个程序看到,输出是“基类Draw”。显然,这不是所希望的输出,因为

我们知道这个对象实际上是派生类而不只是一个基类。这个调用应当输出“派生类Draw”

。为此,由基类派生的任何对象应当使它的Draw版本被使用。然而,当对函数用C方法时,

以上的标现并不奇怪。为了理解这个问题,需要知道捆绑的概念。

二 函数调用捆绑:

把函数体与函数调用相联系称为捆绑(binding)。当捆绑在程序运行之前(由编译

器和连接器)完成时,称为早捆绑。我们可能没有听到过这个术语,因为在过程语言中是

不会有的:C编译只有一种函数调用,就是早捆绑。上面程序中的问题是早捆绑引起的,因

为编译器在只有jilei地址时它不知道正确的调用函数。解决方法被称为晚捆绑,这意味着

捆绑在运行时发生,基于对象的类型。晚捆绑又称为动态捆绑或运行时捆绑。当一个语言

实现晚捆绑时,必须有一种机制在运行时确定对象的类型和合适的调用函数。这就是,编

译器还不知道实际的对象类型,但它插入能找到和调用正确函数体的代码。晚捆绑机制因

语言而异,但可以想象,一些种类的类型信息必须装在对象自身中。稍后将会看到它是如

何工作的。

三 虚函数

对于特定的函数,为了引起晚捆绑, C + +要求在基类中声明这个函数时使用

virtual关键字。晚捆绑只对virtual起作用,而且只发生在我们使用一个基类的地址时,

并且这个基类中有virtual函数,尽管它们也可以在更早的基类中定义。为了创建一个

virtual成员函数,可以简单地在这个函数声明的前面加上关键字virtual。对于这个函数

的定义不要重复,在任何派生类函数重定义中都不要重复它(虽然这样做无害)。如果一

个函数在基类中被声明为virtual,那么在所有的派生类中它都是virtual的。在派生类中

virtual函数的重定义通常称为越位。

为了在上面的程序中得到所希望的结果,只需简单地在基类中的Draw() 之前加关

键字:virtual.

如下所示:

#include<iostream.h>

class jilei

{

public:

virtual void Draw();

};

void jilei::Draw()

{

cout<<"基类Draw"<<endl;

}

class paishenglei:public jilei

{

public:

void Draw();

};

void paishenglei::Draw() //只需对基类编程

{

cout<<"派生类Draw"<<endl;

}

void Play(jilei &j)

{

j.Draw();

}

void main(void)

{

jilei jl;

paishenglei psl;

Play(jl);

Play(psl); //向上映射,输出为“派生类Draw”

}

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
 
© 2005- 王朝網路 版權所有 導航