第六章 多态性与重载精品.ppt
文本预览下载声明
第六章 多态性与重载 6.1 程序的多态性 多态性指在程序中同一符号或名字在不同情况下具有不同解释的现象(polymorphism)。在面向对象程序设计语言中,由程序员设计的多态性有两种基本的形式:编译时多态性和运行时多态性。 编译时多态性是指在程序编译阶段即可确定下来的多态性,主要通过使用重载机制获得,重载机制包括函数重载和运算符重载两大类。函数重载允许程序员用相同的名字定义两个或更多的C++函数,使得语义非常相似的函数可以用同样的标识符来命名。运算符重载允许程序员重新定义C++语言已有的运算符,以一种更自然的方式使用程序员自己定义的类的类型。 运行时多态性是指必须等到程序运行期间才能确定的多态性,主要通过继承结合动态绑定获得。要产生运行时多态性必须先设计一个类层次,然后在某些类中使用虚函数。虚函数与普通函数的区别在于函数名字与函数实体的绑定方式不同,普通函数使用的是静态绑定,而虚函数使用的是动态绑定。 6.2 函数重载 在C++语言中,只要在声明函数原型时形式参数的个数或对应位置的类型不同,两个或更多的函数就可以共用同一个名字。这种在同一作用域中允许多个函数使用同一个函数名的措施称为重载(overloading)。函数重载是C++程序获得多态性的途径之一。 C语言不支持重载,所以每个函数都必须具有唯一的一个名字。如C语言的数学函数库中提供了三个函数求绝对值:abs()、labs()和fabs()。尽管这些函数完成的任务非常相似,但必须定义为三个函数。而C++中只需使用abs()来实现,编译程序可以根据实际参数相应位置的类型选择调用哪一个版本的重载函数。 函数重载的注意事项: 返回值类型不能用于区分重载 如:int get_value( int index ); double get_value( int index ); 这两个函数不是重载函数,编译程序认为这是对一个函数的重复说明,因为两个函数的形式参数个数与对应位置的类型完全相同。 用typedef定义的类型不能用于区分重载 如:typedef double MONEY; double calculate( double income ); MONEY calculate( MONEY income); 由typedef定义的类型别名并没有真正创建一个新的类型,所以不能用于定义重载函数形参的数据类型。 不同参数传递方式不能用于区分重载 如:void func( int value ); void func( int value ); 不同参数传递方式也无法区别重载函数,因此如此的用法也是错误的。 重载的二义性: 重载的二义性(ambiguity)是指C++编译程序无法在多个重载函数中选择正确的函数进行调用。这些二义性错误是致命的,因而编译程序无法生成目标代码。函数重载的二义性主要源于C++语言的隐式类型转换与缺省参数。 在函数调用时,编译程序将按以下规则选择重载函数:如果函数调用的实际参数类型与一个重载函数的形式参数类型完全匹配,则选择该重载函数;如果找不到与实际参数类型完全匹配的函数原型,但如果按照类型转换规则,可将一个类型转换为其他类型后,能找到完全匹配的函数类型,编译程序选择调用该重载函数,如: int func( double d ); …… coutfunc(‘A’); 虽然没有声明函数原型int func( char ),但函数调用func(‘A’)并不会产生任何问题,这是因为编译程序自动将字符‘A’转换为double类型,然后调用函数int func( double )。 隐式类型转换引起的二义性 如: float ab( float x ) { return ( x=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; } 程序定义了两个重载函数ab()用于计算float和double类型数据的绝对值,主函数中第一次调用-3.14时,由于实参是double类型,因而不存在二义性问题,但调用-5时,实参是int类型,则到底要转换成float还是double 就会存在二义性问题。 使用缺省参数引起的二义性 在重载函数中使用缺省参数也可能引起二义性。 如: #includeiostream.h int func( int i ) { return i; } in
显示全部