《多态性与重载讲稿.ppt》由会员分享,可在线阅读,更多相关《多态性与重载讲稿.ppt(19页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、多态性与重载第一页,讲稿共十九页哦6.1 程序的多态性多态性指在程序中同一符号或名字在不同情况下具有不同解释的现象(polymorphism)。在面向对象程序设计语言中,由程序员设计的多态性有两种基本的形式:编译时多态性和运行时多态性。编译时多态性是指在程序编译阶段即可确定下来的多态性,主要通过使用重载机制获得,重载机制包括函数重载和运算符重载两大类。函数重载允许程序员用相同的名字定义两个或更多的C+函数,使得语义非常相似的函数可以用同样的标识符来命名。运算符重载允许程序员重新定义C+语言已有的运算符,以一种更自然的方式使用程序员自己定义的类的类型。运行时多态性是指必须等到程序运行期间才能确定
2、的多态性,主要通过继承结合动态绑定获得。要产生运行时多态性必须先设计一个类层次,然后在某些类中使用虚函数。虚函数与普通函数的区别在于函数名字与函数实体的绑定方式不同,普通函数使用的是静态绑定,而虚函数使用的是动态绑定。第二页,讲稿共十九页哦6.2 函数重载在C+语言中,只要在声明函数原型时形式参数的个数或对应位置的类型不同,两个或更多的函数就可以共用同一个名字。这种在同一作用域中允许多个函数使用同一个函数名的措施称为重载(overloading)。函数重载是C+程序获得多态性的途径之一。C语言不支持重载,所以每个函数都必须具有唯一的一个名字。如C语言的数学函数库中提供了三个函数求绝对值:abs
3、()、labs()和fabs()。尽管这些函数完成的任务非常相似,但必须定义为三个函数。而C+中只需使用abs()来实现,编译程序可以根据实际参数相应位置的类型选择调用哪一个版本的重载函数。第三页,讲稿共十九页哦函数重载的注意事项:返回值类型不能用于区分重载 如:int get_value(int index);double get_value(int index);这两个函数不是重载函数,编译程序认为这是对一个函数的重复说明,因为两个函数的形式参数个数与对应位置的类型完全相同。用typedef定义的类型不能用于区分重载如:typedef double MONEY;double calcula
4、te(double income);MONEY calculate(MONEY income);由typedef定义的类型别名并没有真正创建一个新的类型,所以不能用于定义重载函数形参的数据类型。不同参数传递方式不能用于区分重载如:void func(int value);void func(int&value);不同参数传递方式也无法区别重载函数,因此如此的用法也是错误的。第四页,讲稿共十九页哦重载的二义性:重载的二义性(ambiguity)是指C+编译程序无法在多个重载函数中选择正确的函数进行调用。这些二义性错误是致命的,因而编译程序无法生成目标代码。函数重载的二义性主要源于C+语言的隐式类
5、型转换与缺省参数。在函数调用时,编译程序将按以下规则选择重载函数:如果函数调用的实际参数类型与一个重载函数的形式参数类型完全匹配,则选择该重载函数;如果找不到与实际参数类型完全匹配的函数原型,但如果按照类型转换规则,可将一个类型转换为其他类型后,能找到完全匹配的函数类型,编译程序选择调用该重载函数,如:int func(double d);cout=0?x:-x);double ab(double x)return(x=0?x:-x);int main(int argc,char*argv)coutab(3.14)n;coutab(-5)n;getchar();return 0;程序定义了两个
6、重载函数ab()用于计算float和double类型数据的绝对值,主函数中第一次调用-3.14时,由于实参是double类型,因而不存在二义性问题,但调用时,实参是int类型,则到底要转换成float还是double 就会存在二义性问题。第六页,讲稿共十九页哦使用缺省参数引起的二义性在重载函数中使用缺省参数也可能引起二义性。如:#includeint func(int i)return i;int func(int i,int j=10)return i*j;int main(int argc,char*argv)coutfunc(3,4)n;coutfunc(5)Edit1-Text.c_s
7、tr();return temp_obj;第十四页,讲稿共十九页哦运算符重载 C+语言的函数重载机制为程序员提供了很大的灵活性,在加上运算符重载机制后,在某些应用领域中我们就能够以一种更自然的方式来编写程序。在类中重载一个运算符实质上是在类中定义一个运算符函数,它与定义一个重载函数非常类似,只不过要用保留字operator加上运算符来命名函数。类成员运算符重载的一般形式为:类型 类名:operator运算符(参数表)/运算符函数体其中,尽管运算符函数的返回值类型可以是任意的,但一般设计为当前的类类型以便进行复合运算,与重载函数不同,运算符函数的参数受到所重载的运算符的约束,不可随意指定。第十五
8、页,讲稿共十九页哦重载二元运算符作为一个类的成员函数时,只需要给它显式地传递一个参数,而另一个参数缺省地规定为this指针,且对应的实际参数必须是二元运算的左操作数;同样道理,一元运算符函数使用的参数是缺省规定的this指针。因而重载二元运算符要求一个参数,重载一元运算符不用参数。定义二元运算符函数时,在函数中使用this指针相当于使用左操作数,而右操作数是显式地传递的。函数体可以修改左操作数的值,但能否修改右操作数的值取决于右操作数的传递方式。如:temp.real=real+other.real;相当于 temp.real=this-real+other.real;这样就相当于使用了两个参
9、数。在重载二元运算符时必须注意两个操作数的左右位置。对于加法而言,由于加法可交换,所以操作数的次序不会产生什么影响。但对于减法运算而言,左右操作数位置的不同将导致运算结果的不同,所以必须正确地认识两个参数的次序。在使用重载运算符时,采用运算符原来的表达式形式。如主函数中使用c1+c2,这时相当于调用运算符左边对象c1的运算符函数“+”,并通过this指针隐式地将c1传递给运算符函数“+”,运算符右边对象c2作为另一个参数传递给运算符函数“+”。第十六页,讲稿共十九页哦友元运算符重载运算符重载中,二元运算符只带一个右参数,左操作数必须与定义的类类型相同,否则就会出错。如复数的实验中若最后的运算式
10、改为c3=10-c1;则为非法的,因为“-”的左操作数必须是一个COMPLEX类型的对象。可以使用强制类型转换,如c3=COMPLEX(10)-c1;但,麻烦又不直观。另一种解决途径就是使用友元运算符重载来取代类成员运算符。友元运算符的参数规则与类成员运算符不同,一元运算符函数必须显式地声明一个参数,二元运算符函数必须显式声明两个参数,因为友元函数并不是一个类成员函数,在友元函数体中,不能使用this指针。当一个运算符的操作需要修改类对象状态时,应该以成员函数重载。例如,需要左值操作数的运算符(如=、*=、+等)应该用成员函数重载。如果以友元函数重载,可以使用引用参数修改对象。当希望运算符的操
11、作数(尤其是第一个操作数)有隐式转换,则重载运算符时必须用友元函数或普通函数。第十七页,讲稿共十九页哦重载运算符的限制C+语言中大部分预定义运算符都可以被重载,以下列出可以重载的运算符:+-*/%&|!=+=-=*=/=%=&=|=!=&|+-*-()new delete new delete只有几个运算符不能被重载:.*:?:sizeof第十八页,讲稿共十九页哦运算符重载的其他规则在C+语言中,运算符重载具有很大的灵活性,但也必须遵循以下限制:1.重载运算符无法改变任何运算符的优先级与结合性质;2.重载运算符不可改变运算符的操作数个数;3.重载运算符不可使用缺省参数;4.除了赋值运算符外,重载运算符可由派生类继承下去;5.运算符=、()、和-可作为类成员运算符,但不可作为友元运算符。C+语言运算符重载的高度灵活性容易导致初学者进入一个误区,在不应该使用运算符重载的时候使用运算符重载。应用运算符重载的前提应该是保持运算符的语法与语义习惯,因而运算符重载主要用于与数学相关的领域。在其他情况下,使用有含义的标识符作为函数的名字比运算符重载更容易理解与掌握。第十九页,讲稿共十九页哦
限制150内