《运算符重载和自定义类型变换精.ppt》由会员分享,可在线阅读,更多相关《运算符重载和自定义类型变换精.ppt(29页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、运算符重载和自定义运算符重载和自定义类型变换类型变换第1页,本讲稿共29页方法重载概述方法重载概述n n面向对象程序设计的一个重要特征,是一种临时多态性n n重载决策是一种编译时机制,用于在给定了参数列表和重载决策是一种编译时机制,用于在给定了参数列表和一组候选函数成员的情况下,由编译器选择一个最佳函一组候选函数成员的情况下,由编译器选择一个最佳函数成员来实施调用。数成员来实施调用。n n使得多个具有相同功能但参数不同的方法共享同一个方法名,降低程序员的工作强度,提高程序的可读性n n例:例:double Add(double,double);double Add(double,double)
2、;int Add(int,int);int Add(int,int);第2页,本讲稿共29页方法重载方法重载n重载方法有两种方式n n指定不同个数的参数指定不同个数的参数指定不同个数的参数指定不同个数的参数n n指定不同类型的参数指定不同类型的参数指定不同类型的参数指定不同类型的参数n n重载的“两必须一可以”n n方法名必须相同方法名必须相同n n参数列表必须不同参数列表必须不同n n返回值可以不同返回值可以不同第3页,本讲稿共29页重载方法的调用重载方法的调用签名匹配签名匹配n n对方法调用和方法声明中的参数列表进行匹配,由编译器来完成n n签名匹配算法:1.1.如果能找到,使用精确匹配2
3、.2.尝试标准类型提升3.3.尝试用户自定义转换第4页,本讲稿共29页运算符重载运算符重载n n运算符重载允许为运算指定用户定义的运算符实现,其中一个或两个操作数是用户定义的类或结构类型 n n所有一元和二元运算符都具有可自动用于任何表达式的预定义实现,可通过在类或结构中设置 operator 声明来引入用户定义的实现,其优先级总是高于预定义运算符实现n n重载运算符便于程序员编写同时含有ADT和原生基本类型的中缀表达式,使程序更短,结构更清晰第5页,本讲稿共29页复数类的四则运算复数类的四则运算n n定义一个复数类Complex,将其多个实例进行四则运算,如何编程实现?static void
4、 Main()Complex c1=new Complex(1,2);Complex c2=new Complex(3.5,-2);Complex c3=new Complex(-4,23);/result=c1+c2-c3如何得到?Complex result=c1.Add(c2).Sub(c3);/将Add、Sub改成静态方法会不会更好些?Complex result2=Complex.Sub(Complex.Add(c1,c2),c3);Console.WriteLine(result2.Print();Console.Read();第6页,本讲稿共29页在实现了需要的功能后,有没有一种
5、让用户用更习惯、可读性、可编程性更好的方法来进行类似的运算呢?解决方案:运算符重载!第7页,本讲稿共29页可重载的运算符可重载的运算符n n一元运算符+-!+-true falsen n二元运算符+-*/%&|=!=第8页,本讲稿共29页 public class Complex public int real;public int imaginary;public Complex()public Complex(int real,int imaginary)this.real=real;this.imaginary=imaginary;public static Complex operat
6、or+(Complex c1,Complex c2)return new Complex(c1.real+c2.real,c1.imaginary+c2.imaginary);public static Complex operator-(Complex c1,Complex c2)return new Complex(c1.real-c2.real,c1.imaginary-c2.imaginary);public override string ToString()return(String.Format(0+1i,real,imaginary);二二二二元元元元运运运运算算算算符符符符重
7、重重重载载载载示示示示例例例例注意函数原形!注意函数原形!第9页,本讲稿共29页 public static void Main()Complex num1=new Complex(3,4);Complex num2=new Complex(3,4);Complex num3=new Complex(-3,4);Complex sum=num1.Add(num2);Complex result=num1+num2-num3;Console.WriteLine(First complex number:0,num1);Console.WriteLine(Second complex number
8、:0,num2);Console.WriteLine(The sum of the two numbers:0,sum);Console.WriteLine(The result:0,result);Console.WriteLine(num1=num2);Console.Read();自动调用自动调用num1num1的的ToStringToString()()第10页,本讲稿共29页 public static bool operator=(Complex c1,Complex c2)if(c1.real=c2.real&c1.imaginary=c2.imaginary)return tr
9、ue;else return false;public static bool operator!=(Complex c1,Complex c2)if(c1.real=c2.real&c1.imaginary=c2.imaginary)return false;else return true;对对=重载一定要重载一定要对对!=!=也进行重载,也进行重载,否则编译器报错否则编译器报错第11页,本讲稿共29页重写重写Equals和和GetHashCode方法方法n n警告1:“ConsoleApplication3.Complex”定义运算定义运算符符 =或运算符!=!=,但不重写 Object
10、.Equals(object o)Object.Equals(object o)和和GetHashCode方法方法 n n对于引用类型来说,对于引用类型来说,Object.EqualsObject.Equals方法比较的是对象方法比较的是对象的相等性。当引用指向同一个对象的时候,它们是相等的相等性。当引用指向同一个对象的时候,它们是相等的,具有相同状态但指向不同对象的引用是不相等的的,具有相同状态但指向不同对象的引用是不相等的 n n对于值类型来说,对于值类型来说,Equals已经重写过以进行值的比较 第12页,本讲稿共29页GetHashCoden n重载重载EqualsEquals必须重载
11、必须重载GetHashCoden n这是一条编译器的rule。如果你重载了。如果你重载了EqualsEquals不重载GetHashCodeGetHashCode,编译器会发出警报,编译器会发出警报n nGetHashCodeGetHashCode需要返回一个需要返回一个Int32Int32值,这个值得规律很简单:值,这个值得规律很简单:n n如果两个对象相同,则对象返回的如果两个对象相同,则对象返回的HashCodeHashCode必须相同。必须相同。n n如果两个对象返回的如果两个对象返回的HashCodeHashCode不相同,则这两个对象必定不相不相同,则这两个对象必定不相同。同。n
12、n两个对象不相同,不能保证两个对象不相同,不能保证hashCodehashCode不同?不同?n n这样就使得这样就使得EqualsEquals的效率提高很多。因为的效率提高很多。因为GetHashCodeGetHashCode通通常成本比常成本比Equals小得多。第13页,本讲稿共29页 public static bool operator=(Complex c1,Complex c2)if(c1.real=c2.real&c1.imaginary=c2.imaginary)return true;else return false;public static bool operator
13、!=(Complex c1,Complex c2)if(c1.real=c2.real&c1.imaginary=c2.imaginary)return false;else return true;public override bool Equals(object obj)Complex temp=obj as Complex;if(this=temp)return true;return false;public override int GetHashCode()/返回返回当前对象的哈希代码当前对象的哈希代码,不唯一!return this.ToString().GetHashCode
14、();第14页,本讲稿共29页整理一下,这样更好整理一下,这样更好 public override bool Equals(object obj)Complex temp=obj as Complex;if(temp.real=this.real&temp.imaginary=this.imaginary)return true;return false;public static bool operator=(Complex c1,Complex c2)return c1.Equals(c2);public static bool operator!=(Complex c1,Complex
15、c2)return!c1.Equals(c2);public override int GetHashCode()return this.ToString().GetHashCode();第15页,本讲稿共29页思考思考n n如何实现复数的其他运算?加/减乘/除取反显示第16页,本讲稿共29页自定义类型转换自定义类型转换n n现在,如果要实现int+Complex怎么办呢?n n还有,complex+intComplex+doubledouble+complexfloat+ComplexComplex+float。n n为每种运算定义重载太麻烦了,有更好的办法自定义类型转换第17页,本讲稿共2
16、9页用户自定义变换用户自定义变换l在不希望进行隐式类型变换或者表达式不合法时,有必要对表达式进行用户自定义的类型变换。lC#支持将用户自定义的ADT和内建的数据类型进行集成lC#使用关键字implicit和explicit来修改单参数的静态方法第18页,本讲稿共29页用户自定义的隐式变换用户自定义的隐式变换n nImplicit关键字 用于声明用户定义的隐式类型转换运算符,可通过消除不必要的类型转换来提高源代码的可读 class MyType class MyType public static implicit operator int(MyType m)public static impl
17、icit operator int(MyType m)/code to convert from MyType to int /code to convert from MyType to int MyType x;int i=x;/implicitly call MyTypes MyType-to-int conversion operator第19页,本讲稿共29页用户自定义的显式变换用户自定义的显式变换n nexplicit 关键字 用于声明用户定义的显式类型转换运算符class MyTypeclass MyType public static explicit operator MyT
18、ype(int i)public static explicit operator MyType(int i)/code to convert from int to MyType /code to convert from int to MyType int i;MyType x=(MyType)i;/int-to-MyType requires cast第20页,本讲稿共29页为为Complex类添加自定义类型转换类添加自定义类型转换Complex num1=new Complex(2,3);Complex num2=new Complex(3,4);Complex num3=4.5;Co
19、mplex sum=num1+3+num2;Console.WriteLine(The sum of the 3 numbers:0,sum);/从实数到复数的自定义隐式转换从实数到复数的自定义隐式转换/复数的实部复数的实部/public static implicit operator Complex(double r)return new Complex(r,0);两次隐式转换:1)int-double2)double-Compleximplicit改成改成explicit将会如何将会如何?第21页,本讲稿共29页显式自定义类型转换显式自定义类型转换public static explic
20、it operator Complex(double r)return new Complex(r,0);public static void Main()Complex num1=new Complex(2,3);Complex num2=new Complex(3,4);Complex num3=(Complex)4.5;Complex sum=num1+(Complex)3+num2;Console.WriteLine(The sum of the 3 numbers:0,sum);更多运算符重载的例子。更多运算符重载的例子。第22页,本讲稿共29页 public class DoubO
21、p public DoubOp(int i,int j)x=i;y=j;public static DoubOp operator+(DoubOp a)a.x+;a.y+;return a;public static DoubOp operator-(DoubOp a)a.x-;a.y-;return a;public void Print()Console.WriteLine(this.x+this.y);int x,y;class Testpublic static void Main()DoubOp a=new DoubOp(10,29);a.Print();a+;a.Print();a
22、-;a.Print();一一一一元元元元运运运运算算算算符符符符重重重重载载载载示示示示例例例例第23页,本讲稿共29页二二二二元元元元运运运运算算算算符符符符重重重重载载载载示示示示例例例例public class Angle public int deg,min,sec;public Angle(int degree,int minute,int second)this.deg=degree;this.min=minute;this.sec=second;public static Angle operator+(Angle a,Angle b)Angle t=new Angle(0,0,
23、0);t.sec=a.sec+b.sec;if(t.sec=60)t.sec-=60;t.min+=1;t.min+=a.min+b.min;if(t.min=60)t.min-=60;t.deg+=1;t.deg+=a.deg+b.deg;return t;public override string ToString()return(deg+min+sec+“);第24页,本讲稿共29页class Testpublic static void Main()Angle m=new Angle(10,20,30);Angle n=new Angle(40,50,50);Console.Writ
24、eLine(m+n);Console.Read();第25页,本讲稿共29页重载关系运算符重载关系运算符public static bool operator (Angle a,Angle b)public static bool operator (Angle a,Angle b)if(a.degb.deg)return true;if(a.degb.min)return true;if(a.minb.min)return false;if(a.minb.sec)return true;return false;return false;重载关系运算应保持运算结果与一般的关系运算相同,即应为
25、bool重载了重载了 必须同时重载必须同时重载=必须同时重载必须同时重载=第26页,本讲稿共29页运算符重载注意点运算符重载注意点n n不能被重载的运算符:成员访问、方法调用或成员访问、方法调用或 =、&、|、?:?:、checked、unchecked、newnew、typeof、as as 和和 is is 运算符n n当重载一个二元运算符时,也会隐式重载相应的赋值运算符(若有)n n强制转换运算(如(T)x)通过提供用户定义的转换来重载。n n一元或二元运算符重载只能作为静态方法实现n n应尽可能保持运算符含义的一致性第27页,本讲稿共29页拾遗拾遗ToString()n nC#C#中的
26、每个对象都继承中的每个对象都继承 ToStringToString 方法方法,此方法返回该对象的字符串此方法返回该对象的字符串表示形式。表示形式。n n例:例:Console.WriteLine(“0is a luck number”,i);Console.WriteLine(“0is a luck number”,i);相当于调用了相当于调用了int.ToString()int.ToString()n npublic static void Main()public static void Main()Angle m=new Angle(10,20,30);Angle m=new Angle
27、(10,20,30);Angle n=new Angle(40,50,50);Angle n=new Angle(40,50,50);Console.WriteLine(m+n);/Console.WriteLine(m+n);/将将mm与与n n的和格式化后输出的和格式化后输出Console.Read();Console.Read();n n如果要输出如果要输出m+n=?m+n=?的完整公式怎么作?的完整公式怎么作?n nConsole.WriteLine(m+”+”+n+”=“+(m+n);Console.WriteLine(m+”+”+n+”=“+(m+n);第28页,本讲稿共29页练习题练习题n n定义一个三维空间坐标类,包含三个分量的值(x,y,z),如何对两个坐标点进行加、减运算n n为复数类添加乘/除运算符重载第29页,本讲稿共29页