首页/技术开发/内容

第9章 办法[《.net框架程序设计》读书笔记]

技术开发2024-01-08 阅读()
=、^=、<<=、>>=,实际上其中一些“复式操作符”在二元操作符被重载后自动生成,而不能显式定义

l 必须成对重载的操作符:(== ,!=)、(<,>)、(<=,>=)

l ++、--操作符重载时不能区分其为前置或后置的

2、 操作符重载与语言互操作性

编译器会为重载的操作符生成一个特殊名称的方法,如+(加)操作符生成op_Addition()方法,并为该方法的定义条目上加上specialname标记。当某种语言不能进行操作符重载时,可以直接定义具有该特殊名称的方法,以在其他语言中调用;或直接调用具有该特殊名称的方法以适应某种语言不能解析操作符的限制。如:vb中不能重载操作符,可显式定义op_Addition()方法以在C#中调用;C#中定义的+操作符不能被VB识别,可显式调用op_Addition()方法获得同样的功能。

四、 转换操作符

转换操作符的一些限制:

l 必须为public static

l 必须指定关键字implicit或explicit,原则为:从本类型转换为其他类型使用implicit,将其他类型转换为本类型用explicit,不能都使用implicit



五、 方法参数

1、 引用参数

l 缺省情况下为值传递

l 标志为out的参数,在调用方法前不必初始化,但返回之前必须赋值,没有被初始化的参数是不能被使用

l 标志为ref的参数,在调用方法前必须初始化,否则触发编译错误

l 可以使用ref或out来进行方法的重载,但不能通过区分ref和out来重载方法

l 按引用方式传递的变量(实参)必须和方法声明的参数(形参)类型完全相同,否则触发编译错误。

2、 可变数目参数

使用params关键字及对象数组的方式指定可变参数序列。一些限制:

l 只有方法的最后一个参数才能使用可变数目参数



六、 虚方法

1、 虚方法的调用机理

CLR使用以下两个IL指令调用方法:

u call 根据类型(即引用的静态类型、声明类型)来调用一个方法

u callvirt 根据对象(即引用的动态类型、实际类型)来调用一个方法

对于虚方法使用call来调用的情况有:

l base.虚方法(),

l 密封类型引用虚方法,因为没有必要检验密封类型的实际类型

l 值类型,避免被装箱

使用callvirt调用非虚方法的情况:

l 应用变量为null时,使用callvirt才会抛出System.NullReferenceException异常,而call不会抛出

无论call或callvirt调用方法,均会有一个隐含的this指针作为方法的第一个参数,它指向正在操作的对象

2、 虚方法的版本控制:

用下面的例子说明:

using System;



class BaseClass

{

public void NonVirtualFunc()

{

Console.WriteLine("Non virtual func in base class");

}



public virtual void VirtualFunc()

{

Console.WriteLine("Virtual func in base class");

}

}



class DevicedClass : BaseClass

{

//若不使用new 关键字则编译器会有warning:

//“DevicedClass.NonVirtualFunc()”上要求关键字

//new,因为它隐藏了继承成员“BaseClass.NonVirtualFunc()”

public new void NonVirtualFunc()

{

Console.WriteLine("Non virtual func in deviced class");

}

//若不添加关键字override或new,则编译器会有warning:

//“DevicedClass.VirtualFunc()”将隐藏继承的成员“BaseClass.VirtualFunc()

//”。若要使当前成员重写该实现,请添加关键字 override。否则,添加关键字

//new。

public override void VirtualFunc()

{

Console.WriteLine("Virtual func in deviced class");

}

}



class TestClass

{

public static void Main()

{

//派生类实例调用 非虚 及 虚函数

DevicedClass dc = new DevicedClass();

dc.NonVirtualFunc();

dc.VirtualFunc();



//基类实例调用 非虚 及 虚函数

BaseClass bc = new BaseClass();

bc.NonVirtualFunc();

bc.VirtualFunc();



//指向派生类实例的基类引用 调用 非虚 及 虚函数

BaseClass bc1 = dc;

bc1.NonVirtualFunc();

bc1.VirtualFunc();

}

}



/*

在虚函数上使用关键字override的运行结果:

Non virtual func in deviced class

Virtual func in deviced class

Non virtual func in base class

Virtual func in base class

Non virtual func in base class

Virtual func in deviced class

*/



/*

在虚函数上使用关键字new的运行结果

Non virtual func in deviced class

Virtual func in deviced class

Non virtual func in base class

Virtual func in base class

Non virtual func in base class

Virtual func in base class

*/

由上可见:new 和 override在派生类中协调版本的控制,在第七章中已经看到oeverride只能用于virtual方法,new则可用于非虚或虚方法,以实现隐藏基类中的同名方法。在虚函数上使用override,重写了基类的方法,并无隐藏,这也就实现了多态。我们可设想这样的结论:new使用call指令调用静态类型的方法,而override使用callvirt指令调用动态类型的方法。

希望这个例子对您的理解

第1页  第2页  第3页  第4页 

……

相关阅读