首页 百科知识 虚函数和多态

虚函数和多态

时间:2023-10-16 百科知识 版权反馈
【摘要】:实现这一目的的方法就是虚函数。其中含有三个虚函数可设置报文内容。虚函数被用于支持多态性,即一个类具有多种形态。通过虚函数,可以为不同类型的报文定义不同的行为。在下面的简单程序中,这些函数都被调用,以此理解虚函数的有效范围。这是因为compute_area()是非虚函数,编译器能根据对象的类型轻易确定调用函数的版本。这仅仅是因为square派生于polygon,polygon派生于figuer,而draw()又是虚函数。

3.4 虚函数和多态

通过继承构造新对象的一个原因就是为相同的操作建立不同的行为。也就是说,派生类中定义的行为会覆盖基类中的定义的行为。实现这一目的的方法就是虚函数。虚函数是一种可被派生类覆盖的函数。考虑如下通用报文类。

img65

img66

其中含有三个虚函数可设置报文内容。不同类型的报文需要不同类型的内容。我们用generic_packet作为基类,从它派生出不同类型的报文。

img67

packet_A和packet_B的头部、尾部和净荷格式可能都不同。设置报文各部分格式的方法定义在各派生类中。根据不同的报文类型,虚函数set_header()、set_trailer()和set_body()在子类中有不同的实现。基类generic_packet确定类的结构和可能操作类型,而派生类则可以修改相应操作的行为。

img68

图3-6 IS-A关系的三个类

虚函数被用于支持多态性,即一个类具有多种形态。例如,对报文的某种处理,可能并不需要知道正在处理的报文的类型。唯一必需的信息是正在处理的对象确实是一个报文,也就是说当前报文与基类是IS-A关系。通过虚函数,可以为不同类型的报文定义不同的行为。

参考图3-6中的三个类,它们之间互为IS-A关系,通过它们可加深理解虚函数的工作机制。

figure是基类,polygon是其子类,而square又是polygon的子类。每个类都定义有两个函数:虚函数draw()和非虚函数compute_area()。SystemVerilog代码如下:

img69

img70

每个函数都以类名::函数名的形式打印自身的全限定名。在下面的简单程序中,这些函数都被调用,以此理解虚函数的有效范围。

img71

程序运行后,打印信息如下:

img72

首先申明square类型的变量s,然后将其分别赋值给f和p。square直接从polygon继承过来,而polygon直接继承于figure。根据打印信息,可推断函数的有效范围,如表3-3所示。

表 3-3

img73

在任何情况,compute_area()都由调用它的句柄类型决定,如p是polygon的句柄,所以打印信息为polygon::compute_area()。这是因为compute_area()是非虚函数,编译器能根据对象的类型轻易确定调用函数的版本。

而draw()是虚函数,编译器难以决定调用哪个函数,只能在运行时,通过一个虚拟的函数绑定表决定。在此不讨论虚拟表机制,详情可参见Stanley B.Lippman的《Inside the C++ Object Model》。

注意到,虽然p是polygon类型,但调用p.draw()输出结果却是square::draw(),而不是所期望的polygon::draw()。变量f的情况也相同:f.draw()输出结果是square::draw()。原始例化的对象是square类型,尽管它被赋给不同类型的句柄,但它是square类型变量却始终不会改变。这仅仅是因为square派生于polygon,polygon派生于figuer,而draw()又是虚函数。

如果s不是派生于p,s赋值给p,将会导致编译错误。

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈