购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP


陷阱11
三思而行
——构造方法中调用虚方法的陷阱

1.陷阱产生的场景

C#是一种完全面向对象的语言,构造函数和虚方法都是面向对象中非常重要的元素,构造方法用来创建对象,虚方法常用来在子类中被重写。本实例中将向各位读者演示在构造函数中调用虚方法的实现过程。

例4.11 构造方法中调用虚方法的陷阱(光盘位置:光盘\MR\Instance\4\11\ Fransfer VirtualFunction),该实例的实现过程如下。

首先在本实例的Program.cs类文件中编写3个类,名称分别为Ref、Parent、Child。这3个类的关系如图4.18所示。

图4.18 类关系图

在这3个类中,Parent是Child的基类(或超类),Child是Parent的子类(或派生类)。在这两个类中都有对Ref类的引用。下面是这3个类的代码:

说明

在Parent类的构造方法中,调用了虚方法GetString。

本实例创建的是一个控制台应用程序,于是在Main方法中编写了实例化Child类的代码,具体代码如下:

上面的代码在编译时,没有任何问题,但在执行时却出现了异常,如图4.19所示。

2.陷阱的分析

解决问题最快、最直接的办法就是在代码中设置断点,然后跟踪断点、分步调试。于是在应用程序的Main方法中设置断点,在跟踪断点时发现,在执行Child类的构造函数代码之前先执行Parent类的构造函数,当执行到调用虚方法的代码时,突然断点跳转到Child类的GetString方法体中,在执行该方法体中的my2.str代码时出错,因为my2在Child类的构造函数中被实例化,而此时代码还未执行到Child类的构造函数,所以出现上面的异常。代码执行顺序如图4.20所示。

图4.19 异常信息提示

图4.20 代码执行顺序

当一个虚方法被调用时,CLR总是根据对象的实际类型来找到应该被调用的方法定义。也就是说,当虚方法在基类的构造函数中被调用时,它的类型仍然保持子类类型,子类的虚方法将被执行,这就是断点从Parent类的构造函数突然跳转到Child类的GetString方法的原因。

3.陷阱的解决方法

该问题的解决方法只有一个,那就是永远不要在子类的构造函数中调用虚方法。 3Lmrr80QD3rVOFRMsG52QRKu72ZwsHsi7+vQmLDkAJGn1XeQISvzJMBhHwo9ywe8

点击中间区域
呼出菜单
上一章
目录
下一章
×