[华工课件]C++程序设计基础(第三版)chap9-虚函数与多态性
电子工业出版社C 程序设计基础第3版答案 华南理工大学
习题1及其解答1.1选择题1.一个最简单的C++程序,可以只有一个( c )。
(a) 库函数(b) 自定义函数(c) main函数(d) 空函数2.用C++语言编制的源程序要变为目标程序必须要经过( d )。
(a) 解释(b) 汇编(c) 编辑(d) 编译3. C++程序中的简单语句必须以( b )结束。
(a) 冒号(b) 分号(c) 空格(d)花括号4.有说明 int a=0; double x=5.16; 以下语句中,( c )属于编译错误。
(a) x=a/x; (b) x=x/a; (c) a=a%x; (d) x=x*a;5. 执行C++程序时出现的“溢出”错误属于( c )错误。
(a) 编译(b) 连接(c) 运行(d) 逻辑6.下列选项中,全部都是C++关键字的选项为( c )。
(a) while IF Static (b) break char go(c) sizeof case extern (d) switch float integer7. 按C++标识符的语法规定,合法的标识符是( a )。
(a) _abc (b) new (c) π(d) “age“8.C++语句中,两个标识符之间( a )不能..作为C++的分隔符。
(a) 数字(b) ; (c) : (d) +9.下列正确的八进制整型常量表示是( b )。
(a) 0a0 (b) 015 (c) 080 (d) 0x1010.下列错误的十六进制整型常量表示是( c )。
(a) 0x11 (b) 0xaf (c) 0xg (d) 0x1f11.在下列选项中,全部都合法的浮点型数据的选项为( b )。
(a) -1e3.5 15. 2e-4 (b) 12.34 -1e+5 0.1E-12(c) 0.2e-2 -12345. e-5 (d) 5.0e(1+4) 0.1 8e+212.下列正确的字符常量为( d )。
(a) “a”(b) ‟(c) a (d) (101)13.下列选项中,( d )不能..交换变量a和b的值。
《C 程序设计实例与操作》课件第10章 多态性、虚函数与运算符重载
t.imag=imag+c.imag;
return t;
} 则a+b为隐式调用,它等价于a.operator+(b),这是显式调用。
2.单目运算符重载作为类的成员函数
单目运算符重载作为类的成员函数时,操作数为访问该重 载运算符的对象本身的数据,也由this指针指出,因此,单目 运算符重载函数没有参数。
2.赋值运算符的重载
通常情况下,系统会自动生成一个默认的赋值运算符函数, 提供同类对象之间进行赋值的功能。但在某些特殊情况下,必 须要定义一个赋值运算符重载函数。
10.5 实现类型转换
类型转换函数用来将类类型转换为标准数据类型。
operator 类型名() { 转换语句 } 类型转换函数只能作为成员函数,不能作为友元函数,它又 称为类型转换运算符重载函数。
{}
virtual~ Point()
//定义虚析构函数
{}
virtual double CalArea() const=0;
//定义纯虚函数
};
class Rect:public Point {
//定义派生类Rect
protected:
double xcoord1,ycoord1;
public:
双目运算符重载为友元函数时,由于没有this指针,所以 操作数要通过友元函数的参数指出。
例如:
operator+(a,b); a+b;
//显式调用 //隐式调用
4.单目运算符重载作为类的友元函数
与双目运算符重载作为友元函数类似,单目运算符重载作 为友元函数时,操作数要通过友元函数的参数指出。
例如:
operator++(a); ++a;
程序设计基础第9讲多态性与虚函数
void Clock::operator ++(int) //后置单目运算符重载 { Second++; if(Second>=60) { Second=Second-60; Minute++; if(Minute>=60){Minute=Minute-60;Hour++;Hour=Hour%24;} } cout<<"Clock++: "; } void main() { Clock myClock(23,59,59); cout<<"First time output:"; myClock.ShowTime(); myClock++; myClock.ShowTime(); ++myClock; myClock.ShowTime(); }
案例9.5 虚函数的应用。
#include <iostream.h> class Mammal //类的声明及其实现 { public: Mammal(){ cout<<"Mammal constructor called."<<endl; } virtual ~Mammal() //用virtual声明虚函数 {cout<<"Mammal destructor called."<<endl;}//虚函数在基类中的实现 virtual void Speak() { cout<<"Mammal speak."<<endl; } }; class Dog:public Mammal //公有派生类Mammal { public: Dog(){ cout<<"Dog constructor called."<<endl; } ~Dog(){ cout<<"Dog destructor called."<<endl; } void Speak() { cout<<"Woof!"<<endl; } //派生类中虚函数的实现 }; void main() { Mammal *p=new Dog; p->Speak(); delete p; }
C多态性和虚函数专题学习PPT课件
整体 概述
一 请在这里输入您的主要叙述内容
二
请在这里输入您的主要 叙述内容
三 请在这里输入您的主要叙述内容
2 2020/7/20
5.1 C++的多态性 派生一个类的原因常常不仅是为了新添加一些描述新事例的变量和
操作函数,而是为了重新定义基类的成员函数。当基类的成员函数在派生 类中重新定义时,其结果是使对象呈现多态性。因此不是整个类都具有多 态性,而是只有类成员函数具有多态性。这种实现方式与自然语言中对动 词的使用很类似。此时动词等价于C++的成员函数。例如一个对象若用 “它”来表示,则在现实生活中可以这样使用:“清洗它,移动它,分解 它,修理它”。这些动词仅代表了一般性动作,因为不知道发生在哪种对 象上。例如,移动铅笔所需的操作完全不同于移动机床所需的操作,尽管 这两个概念是相似的,只有知道“move移动操作”作用的对象,才能将 它与一系列特殊操作联系起来。显然对于不同的对象,“move移动操作 “的具体内容却大不一样。
3 2020/7/20
例 如 , 假 设 我 们 要 把 draw() 函 数 添 加 到 Point 和 Circle 类 中 , Point的draw()函数只是把一个点绘制在屏幕上,而Circle的draw() 函数是以圆的形式画一连串点.
Point p; Circle c;
p.draw(10, 10); c.draw(10, 10, 4);
{ return Complex(real - c.real , imag - c.imag); }
void Print(const Complex &c) { if(c.imag < 0)
cout << c.real << c.imag << 'i' << endl;
《C程序设计》电子教案第9章多态性和虚函数.ppt
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;
4.函数重载的二义性
函数重载的二义性(ambiguity)是指C++语 言的编译程序无法在多个重载函数中选择正确 的函数进行调用。这些二义性错误是致命的, 因而编译程序将无法生成目标代码。函数重载 的二义性主要源于C++语言的隐式类型转换与 默认参数。
例9-4:隐式类型转换造成函数重载二义性示例。
cin>>a>>b; cout<<"矩形周长:"<<length(a,b)<<endl;
} 运行结果为: 输入圆半径:7 ↙ 圆周长:43.981 输入矩形长和宽:3 4 ↙ 矩形周长:14
2.函数重载的表示形式
例9-3:分析以下程序的执行结果。 #include <iostream.h> class Sample {
} 此程序的运行结果为: The square of integer 7 is 49 The square of integer 7.5 is 56.25
《C++程序设计案例教程》第九章多态性和虚函数课件
知识讲解
如果一个类中包含了纯虚函数,则这个类就称为抽象类。纯虚 函数的定义方式如下:
virtual 函数类型 函数名(参数表)=0; 纯虚函数没有函数体。因为纯虚函数不能被调用,所以包含纯 虚函数的不能建立对象。抽象类的作用只是作为一组派生类的基类, 提供公共接口。 虽然抽象类不能定义对象,但可以定义指针变量,将派生类的 地址赋给指针变量,实现用统一的方式调用派生类中的虚函数。 需要注意的是,如果派生类没有重写抽象类中的纯虚函数,那 么纯虚函数被派生类继承后,仍然是纯虚函数,这样只能留给间接 派生类重新定义,抽象类的直接派生类也成为抽象类,也不能建立 对象。
r.Graph::display(); 当然,可以使用指针变量代替对象名调用函数。如果使用指 针变量,可以随时将执行对象的地址赋给指针。这样一来,无 论对象是什么,代码都可以统一采用p->display()的形式。
目录
知识讲解
在继承的机制中,派生类新增的成员函数很可 能与继承得来的基类的成员函数同名,并且参数 个数和参数类型也相同,因此,这种现象不属于 函数重载。如果用派生类对象调用同名的成员函 数,派生类会屏蔽继承的基类的成员函数,执行 自己新增的成员函数。如果要用派生类对象调用 继承的基类同名函数,需要在函数前增加基类名。
A纯dd虚yo函ur数te的xt i使n h用ere
建立纯虚函数,实现虚函数在派生类中的模板作用。
目录
9.2 纯虚函数和抽象类
源代码展示
#include <iostream>
using namespace std;
class Graph
{
public:
virtual void display()=0;
最新《C++程序设计案例教程》习题答案第9章 多态性和虚函数的使用
第9章多态性和虚函数的使用一、选择题1.C. 2.C 3.A 4.C 5. 6.D二、程序题(略)三、简答题1.C++多态性主要体现在哪两个方面?答:在C++中,多态性是指系统调用同名的函数,实现不同的功能。
多态性包含静态多态性和动态多态性。
静态多态性体现在编译时函数重载或者运算符重载上;展现了同一类中多个同名函数的处理机制。
而动态多态性是指程序运行过程中通过虚函数动态地确定针对的对象,展现继承层次结构中同名函数的处理机制。
2. 比较函数重载和虚函数在概念上和使用方式有什么区别。
函数重载是指函数名称相同,但是参数的个数或者参数的数据类型不同。
因此,系统调用重载函数时,会依据参数确定调用哪一个。
而在继承的机制中,基类的成员函数可能会与派生类新增的成员函数同名,包括参数个数和参数类型,这种现象不属于函数重载。
当基类的一个成员函数被声明为虚函数后,其派生类中的同名函数都自动成为虚函数。
派生类可以对虚函数重新定义。
虚函数实现动态多态的问题。
3.比较抽象类、虚函数、纯虚函数的概念和使用上的区别。
虚函数通常在基类中定义,定义可以是空,派生类中可以对虚函数重写,也可以不写。
虚函数起到了接口的默认行为作用。
纯虚函数在基类中是没有定义的,必须在直接或者间接派生类中加以实现,它起到了接口的作用。
包含了纯虚函数的类,被称为抽象类。
抽象类不能建立对象。
4.谈谈虚基类和虚函数,区分两者不同的概念和各自的作用。
在继承机制中,一个派生类继承多个直接基类,而这些基类又有一个公共的基类,这个公共的基类成员在继承中可能产生多个拷贝。
虚基类的基本原则是在内存中只有基类成员的一份拷贝。
这样,通过把基类继承声明为虚拟的,就只能继承基类的一份拷贝,从而消除歧义。
用virtual限定符把基类继承说明为虚拟的。
虚函数指基类中成员函数声明为 virtual ,使它在一个或多个派生类中被重新定义,虚函数的作用是实现多态性。
虚函数必须是基类的非静态成员函数,其访问权限可以protected或public。
C程序设计课件(第3章)
整理ppt
6
3.2.1 运算符重载概述
(3)不能创建新的运算符,只能重载c++中已 有的运算符。
(4)有些运算符不能进行重载。如:“.”类成 员运算符、“*”类指向运算符、“::”类 作用域运算符、“?:”条件运算符及 “sizeof”求字节数运算符。
整理ppt
7
3.2.2 运算符重载的实现
运算符重载的本质就是函数重载。在实现过程 中,首先把指定的运算表达式转化为对运算符函数 的调用,运算对象转化为运算符函数的实参,然后 根据实参的类型来确定需要调用的函数,这个过程 是在编译过程中完成的。运算符重载形式有两种: 重载为类的成员函数和重载为类的友元函数。
整理ppt
3
3.2.1 运算符重载概述
{ real = r, image = i; } void Print(); private: double real, image; }; void Complex::Print() { if(image<0) cout<<real<<image<<'i'; else cout<<real<<'+'<<image<<'i'; }
在以前的学习中,C++中预定义的运算符的操 作对象只能是基本数据类型如int或float等。实 际上,对于很多用户自定义的类型(如类),也需 要有类似的运算操作。
例如复数类Complex。
class Complex
{
public:
Complex () { real=image=0; }
Complex (double r, double i)
最新C++程序设计案例教程精品课件多态性和虚函数
9.1.2 虚函数的使用
运行结果
程序分析
如何通过基类指针调用派生类的同名函数?C++中的虚函数很好地解 决了这个问题。从代码中可以看到,只在基类同名函数声明的前面增 加了关键字virtual,程序运行时,系统就根据指针情况调用了派生类 的同名函数。
知识讲解
虚函数的作用是通过基类指针调用派生类的同名函数。 当基类的一个成员函数被声明为虚函数后,其派生类中的 同名函数都自动成为虚函数。因为基类中已经加了关键字 virtual,所以在声明派生类的同名函数时可以省略关键字。 如果基类中有虚函数,而派生类无同名函数或者派生类没 有对基类的同名函数重新定义,则派生类仍然继承基类的虚 函数。
Click to add Text 案例引入
建立纯虚函数,实现虚函数在派生类中的模板作用。
9.2 纯虚函数和抽象类
源代码展示 #include <iostream> using namespace std; class Graph { public: virtual void display()=0; //定义纯虚函数 }; class Rectangle:public Graph { private: int len,width; public: Rectangle(int l,int w):len(l),width(w){} virtual void display() { cout<<"The rectangle area is
9.1 多态性和虚函数
9.1.1 多态性
分别用对象名和指针变量调用基类和 Add your text in here 派生类中的同名函数
Click to add Text 案例引入
第12章 虚函数与多态性《C程序设计基础教程》
(4) 通过该指针变量调用此虚函数,调用的是
指针变量指向的对象所属类的同名函数。
13
函数重载 PK 虚函数
14
函数重载可用于普通函数和类的成员函数;虚函数 只能用于类的成员函数。
函数重载可用于构造函数;虚函数不可以。
重载成员函数必须属于同一个类,为横向;虚函数 是同一类族中基类和派生类的同原型函数,为纵向。
Circle( ){ } ~Circle( ){cout<<"executing Circle destructor"<<endl;} private: int radius;};
rc1.area( ) //派生类Rectangle的成员函数。 rc1.Point::area( ) //基类Point的成员函数
Pref.area( )
10
12.3 虚函数
11
虚函数的声明形式
virtual <函数类型> <函数名>(<参数列表>) { 函数体 } 成员函数,非static成员函数 有继承性,基类中定义了虚函数,派生类中
{ cout<<“B::display()"; } }; class C: public B { public: void display() //自动成为虚函数
{ cout<<“C::display()"<<endl;} };
void fun(A *ptr) 12 {ptr->display(); } void main() { A a1, *p;
7
class Point
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
9.2.1 基类指针引用派生类对象
#include<iostream> #include<cstring> using namespace std ;
例9-1 使用基类指针引用派生类对象
class A_class
class A_class
{ char name[20] ; public : void put_name( char * s ) { strcpy_s( name, s ) ; } void show_name() { cout << name << "\n" ; }
9.1
静态联编
普通成员函数重载可表达为两种形式:
1. 在一个类说明中重载 2. 基类的成员函数在派生类重载。有 3 种编译区分方法:
(1)根据参数的特征加以区分
例如: void Show ( int , char );
与
void Show ( char * , float ); 不是同一函数,编译能够区分
9.3 虚函数与动态联编
9.4 纯虚函数与抽象类 9.5 虚函数和多态性的应用 小结
华南理工大学计算机学院 周霭如 2009
9.1
静态联编
联编是指一个程序模块、代码之间互相关联的过程。
静态联编,是程序的匹配、连接在编译阶段实现,也称为早期匹配。
重载函数使用静态联编。
动态联编是指程序联编推迟到运行时进行,所以又称为晚期联编。
华南理工大学计算机学院 周霭如 2009
9.1
静态联编
普通成员函数重载可表达为两种形式:
1. 在一个类说明中重载 2. 基类的成员函数在派生类重载。有 3 种编译区分方法:
(1)根据参数的特征加以区分
(2)使用“ :: ”加以区分
例如:
A :: Show ( ); 有别于 B :: Show ( );
};
class B_class : public A_class
{
class B_class : public A_class
char phone_num[ 20 ] ; public : void put_phone( char * num ) { strcpy_s ( phone_num , num ) ; } void show_phone() { cout << phone_num << "\n" ; } 基类指针
};
class B_class : public A_class
{
class B_class : public A_class
char phone_num[ 20 ] ; 基类指针 public : void put_phone( char * num ) { strcpy_s ( phone_num , num ) ; } void show_phone() { cout << phone_num << "\n" ; }
};
int main() { A_class * A_p ; A_class A_obj ; B_class B_obj ; A_p = & A_obj ; A_p -> put_name( "Wang xiao hua" ) ; A_p -> show_name() ; A_p = & B_obj ; A_p -> put_name( "Chen ming" ) ; A_p -> show_name() ; B_obj.put_phone ( "5555_12345678" ); ( ( B_class * ) A_p ) -> show_phone() ; }
华南理工大学计算机学院 周霭如 2009
9.2.1 基类指针引用派生类对象
#include<iostream> #include<cstring> using namespace std ;
例9-1 使用基类指针引用派生类对象
class A_class
class A_class
{ char name[20] ; public : void put_name( char * s ) { strcpy_s( name, s ) ; } void show_name() { cout << name << "\n" ; }
};
基类指针
int main() 指向派生类对象 { A_class * A_p ; A_class A_obj ; B_class B_obj ; A_p = & A_obj ; A_p -> put_name( "Wang xiao hua" ) ; A_p -> show_name() ; A_p = & B_obj ; A_p -> put_name( "Chen ming" ) ; A_p -> show_name() ; B_obj.put_phone ( "5555_12345678" ); ( ( B_class * ) A_p ) -> show_phone() ; }
};
指向基类对象
int main() { A_class * A_p ; A_class A_obj ; B_class B_obj ; A_p = & A_obj ; A_p -> put_name( "Wang xiao hua" ) ; A_p -> show_name() ; A_p = & B_obj ; A_p -> put_name( "Chen ming" ) ; A_p -> show_name() ; B_obj.put_phone ( "5555_12345678" ); ( ( B_class * ) A_p ) -> show_phone() ; }
华南理工大学计算机学院 周霭如 2009
9.1
静态联编
普通成员函数重载可表达为两种形式:
1. 在一个类说明中重载
根据this指针类型区分 2. 基类的成员函数在派生类重载。有 3 种编译区分方法:
(1)根据参数的特征加以区分
(2)使用“ :: ”加以区分 (3)根据类对象加以区分
例如: Aobj . Show ( )
};
class B_class : public A_class
{
class B_class : public A_class
char phone_num[ 20 ] ; public : void put_phone( char * num ) { strcpy_s ( phone_num , num ) ; } void show_phone() { cout << phone_num << "\n" ; }
Bobj . Show ( ) 调用 调用 A :: Show ( ) B :: Show ( )
华南理工大学计算机学院 周霭如 2009
华南理工大学计算机学院 周霭如 2009
9.2 类指针的关系
9.2
类指针的关系
基类指针和派生类指针与基类对象和派生类对象4种可能匹配: 直接用基类指针引用基类对象;
华南理工大学计算机学院 周霭如 2009
9.2.1 基类指针引用派生类对象
#include<iostream> #include<cstring> using namespace std ;
例9-1 使用基类指针引用派生类对象
class A_class
class A_class
{ char name[20] ; public : void put_name( char * s ) { strcpy_s( name, s ) ; } void show_name() { cout << name << "\n" ; }
// 类型 A 的对象
// 类型 B 的对象 // p 指向类型 A 的对象
class B : public A
p = & B_obj ;
// p 指向类型 B 的对象,它是 A 的派生类
利用 p,可以通过 B_obj 访问所有从 A 类继承的元素 , 但不能用 p访问 B 类自定义的元素 (除非用了显式类型转换)
chap9
虚函数与多态性
多态性(Polymorphism)是指一个名字,多种语义;或界面 相同,多种实现。 重载函数是多态性的一种简单形式。 虚函数允许函数调用与函数体的联系在运行时才进行,称为 动2009
第9章
虚函数与多态性
9.1 静态联编 9.2 类指针的关系
};
int main() { A_class * A_p ; A_class A_obj ; B_class B_obj ; A_p = & A_obj ; A_p -> put_name( "Wang xiao hua" ) ; A_p -> show_name() ; A_p = & B_obj ; A_p -> put_name( "Chen ming" ) ; A_p -> show_name() ; B_obj.put_phone ( "5555_12345678" ); ( ( B_class * ) A_p ) -> show_phone() ; }