《C++程序设计》 第9章 多态性与虚函数
合集下载
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第9章 多态性与虚函数
9.1 多态性 9.2 虚函数 9.3 纯虚函数和抽象类
9.1 多态性
9.1.1 普通成员函数重载 9.1.2 构造函数重载 9.1.3 派生类指针
返回首页
9.1.1 普通成员函数重载
1.函数重载的方法 2.函数重载的表示形式 (1)在一个类说明中重载。 (2)基类的成员函数在派生类中重载。 3.函数重载的注意事项 4.函数重载的二义性
year=1999; month=11; day=24; cout<<year<<"/"<<month<<"/"<<day<<endl; } TDate::TDate(int d) { year=1999; month=11; day=d; cout<<year<<"/"<<month<<"/"<<day<<endl; } TDate::TDate(int m,int d) { year=1999; month=m; day=d; cout<<year<<"/"<<month<<”/”<<day<<endl; } TDate::TDate(int y, int m, int d) { year=y; month=m; day=d;
例9-2:用重载函数实现求圆和矩形的周长。
#include <iostream.h> const double PI=3.1415; double length(float r) { return 2*PI*r; } double length(float x,float y) { return 2*(x+y); } void main() { float a,b,r; cout<<"输入圆半径:"; cin>>r;
4.函数重载的二义性
函数重载的二义性( ambiguity)是指 C++ 语 言的编译程序无法在多个重载函数中选择正确 的函数进行调用。这些二义性错误是致命的, 因而编译程序将无法生成目标代码。函数重载 的二义性主要源于 C++ 语言的隐式类型转换与 默认参数。
例9-4:隐式类型转换造成函数重载二义性示例。 #include <iostream.h> float abs(float x) { return (x>0?x:-x); } double abs(double x) { return (x>0?x:-x); } int main() { cout<<abs(1.78)<<endl; //调用abs(double) //cout<<abs(-7)<<endl; // 错误,编译程序无法确定调用 哪一个abs()函数 } 在重载函数中使用默认参数也可能造成二义性。
// 调用构造函数 X() // 调用构造函数 X(int) // 调用构造函数 X(int, char) // 调用构造函数 X(float, char)
例9-6:分析下面程序的执行结果。 #include <iostream.h> class TDate { public: TDate( ); TDate(int d); TDate(int m,int d); TDate(int y,int m,int d); protected: int year; int month; int day; }; TDate::TDate( ) {
返回本节
9.1.2 构造函数重载
构造函数可以像普通函数一样被重载,而且也 可能是 C++ 语言应用函数重载最多的地方,因 为设计一个类时总是希望创建对象的同时能以 多种方式初始化对象的内部状态,而构造函数 只能有一个名字,即该类的名字。当建设一个 可复用类库时,重载构造函数可以更好地提高 类界面的完整性。
例9-3:分析以下程序的执行结果。 #include <iostream.h> class Sample { int i; double d; public: void setdata(int n) { i=n;} void setdata(double x) { d=x;} void disp()
{
cout<<"i="<<i<<",d="<<d<<endl; } }; void main() { Sample s; s.setdata(7); s.setdata(7.5); s.disp(); } 此程序的运行结果为: i=7,d=7.5
有3种编译区分方法: 1)根据参数的特征加以区分。 2)使用“ :: ”加以区分。 3)根据类对象加以区分。
例: class X { public: X ( ) ; X( int ) ; X ( int, char ) ; X ( float, char ) ; …... } ; void f ( ) { X a ; X b ( 1 ) ; X c ( 1, 'c' ) ; X d ( 2.3 , 'd' ) ; ... }
3.函数重载的注意事项
在C++语言中,编译程序选择相应的重载函数版本时函数 返回值类型是不起作用的。不能仅靠函数的返回值来区别 重载函数,必须从形式参数上区别开来。例如: void print(int a); void print(int a,int b); int print(float 3;+编译程序可以从形式参 数上将它们区别开来。但: int f(int a); double f(int a);
1.函数重载的方法
例9-1:给出以下程序的运行结果。 #include <iostream.h> int square(int x) { return x*x; } double square(double y) { return y*y; } main() {
cout<<"The square of integer 7 is"<<square(7)<<endl; cout<<" The square of double 7.5 is"<<square(7.5)<<endl; return 0; } 此程序的运行结果为: The square of integer 7 is 49 The square of integer 7.5 is 56.25
cout<<"圆周长:"<<length(r)<<endl; cout<<"输入矩形长和宽:"; cin>>a>>b; cout<<"矩形周长:"<<length(a,b)<<endl; } 运行结果为: 输入圆半径:7 ↙ 圆周长:43.981 输入矩形长和宽:3 4 ↙ 矩形周长:14
2.函数重载的表示形式
9.1 多态性 9.2 虚函数 9.3 纯虚函数和抽象类
9.1 多态性
9.1.1 普通成员函数重载 9.1.2 构造函数重载 9.1.3 派生类指针
返回首页
9.1.1 普通成员函数重载
1.函数重载的方法 2.函数重载的表示形式 (1)在一个类说明中重载。 (2)基类的成员函数在派生类中重载。 3.函数重载的注意事项 4.函数重载的二义性
year=1999; month=11; day=24; cout<<year<<"/"<<month<<"/"<<day<<endl; } TDate::TDate(int d) { year=1999; month=11; day=d; cout<<year<<"/"<<month<<"/"<<day<<endl; } TDate::TDate(int m,int d) { year=1999; month=m; day=d; cout<<year<<"/"<<month<<”/”<<day<<endl; } TDate::TDate(int y, int m, int d) { year=y; month=m; day=d;
例9-2:用重载函数实现求圆和矩形的周长。
#include <iostream.h> const double PI=3.1415; double length(float r) { return 2*PI*r; } double length(float x,float y) { return 2*(x+y); } void main() { float a,b,r; cout<<"输入圆半径:"; cin>>r;
4.函数重载的二义性
函数重载的二义性( ambiguity)是指 C++ 语 言的编译程序无法在多个重载函数中选择正确 的函数进行调用。这些二义性错误是致命的, 因而编译程序将无法生成目标代码。函数重载 的二义性主要源于 C++ 语言的隐式类型转换与 默认参数。
例9-4:隐式类型转换造成函数重载二义性示例。 #include <iostream.h> float abs(float x) { return (x>0?x:-x); } double abs(double x) { return (x>0?x:-x); } int main() { cout<<abs(1.78)<<endl; //调用abs(double) //cout<<abs(-7)<<endl; // 错误,编译程序无法确定调用 哪一个abs()函数 } 在重载函数中使用默认参数也可能造成二义性。
// 调用构造函数 X() // 调用构造函数 X(int) // 调用构造函数 X(int, char) // 调用构造函数 X(float, char)
例9-6:分析下面程序的执行结果。 #include <iostream.h> class TDate { public: TDate( ); TDate(int d); TDate(int m,int d); TDate(int y,int m,int d); protected: int year; int month; int day; }; TDate::TDate( ) {
返回本节
9.1.2 构造函数重载
构造函数可以像普通函数一样被重载,而且也 可能是 C++ 语言应用函数重载最多的地方,因 为设计一个类时总是希望创建对象的同时能以 多种方式初始化对象的内部状态,而构造函数 只能有一个名字,即该类的名字。当建设一个 可复用类库时,重载构造函数可以更好地提高 类界面的完整性。
例9-3:分析以下程序的执行结果。 #include <iostream.h> class Sample { int i; double d; public: void setdata(int n) { i=n;} void setdata(double x) { d=x;} void disp()
{
cout<<"i="<<i<<",d="<<d<<endl; } }; void main() { Sample s; s.setdata(7); s.setdata(7.5); s.disp(); } 此程序的运行结果为: i=7,d=7.5
有3种编译区分方法: 1)根据参数的特征加以区分。 2)使用“ :: ”加以区分。 3)根据类对象加以区分。
例: class X { public: X ( ) ; X( int ) ; X ( int, char ) ; X ( float, char ) ; …... } ; void f ( ) { X a ; X b ( 1 ) ; X c ( 1, 'c' ) ; X d ( 2.3 , 'd' ) ; ... }
3.函数重载的注意事项
在C++语言中,编译程序选择相应的重载函数版本时函数 返回值类型是不起作用的。不能仅靠函数的返回值来区别 重载函数,必须从形式参数上区别开来。例如: void print(int a); void print(int a,int b); int print(float 3;+编译程序可以从形式参 数上将它们区别开来。但: int f(int a); double f(int a);
1.函数重载的方法
例9-1:给出以下程序的运行结果。 #include <iostream.h> int square(int x) { return x*x; } double square(double y) { return y*y; } main() {
cout<<"The square of integer 7 is"<<square(7)<<endl; cout<<" The square of double 7.5 is"<<square(7.5)<<endl; return 0; } 此程序的运行结果为: The square of integer 7 is 49 The square of integer 7.5 is 56.25
cout<<"圆周长:"<<length(r)<<endl; cout<<"输入矩形长和宽:"; cin>>a>>b; cout<<"矩形周长:"<<length(a,b)<<endl; } 运行结果为: 输入圆半径:7 ↙ 圆周长:43.981 输入矩形长和宽:3 4 ↙ 矩形周长:14
2.函数重载的表示形式