西安工业大学耿军雪老师的C课件之多态性.ppt

上传人:max****ui 文档编号:2842203 上传时间:2019-12-01 格式:PPT 页数:95 大小:692.50KB
返回 下载 相关 举报
西安工业大学耿军雪老师的C课件之多态性.ppt_第1页
第1页 / 共95页
西安工业大学耿军雪老师的C课件之多态性.ppt_第2页
第2页 / 共95页
西安工业大学耿军雪老师的C课件之多态性.ppt_第3页
第3页 / 共95页
点击查看更多>>
资源描述
Object Oriented,面向对象技术与C+,计算机学院,Object Oriented,5-0 分析结果?,#include class point double x,y; public : point (double i,double j) x=i;y=j; double area() return 0.0; ; class rectangle : public point double w,h; public : rectangle(double i,double j,double m,double n):point(i,j) w=m;h=n; double area() return w*h; ; void fun(point ,Object Oriented,第五章 多态性,本章主要内容: 多态性 同一名称,不同的功能实现方式 运算符重载 多态的经典内容 虚函数 动态绑定 纯虚函数 统一接口 抽象类 定义一个框架,由其衍生对象完善,Object Oriented,一、多态性 多态性:是指不同对象在收到相同的消息时,产生不同的动作用同一个名字定义不同的函数,执行不同但相似的操作实现“一个接口,多种方法”。 多态的实现: 函数重载:通过形参来区分 运算符重载:只是一种“语法修饰”,是专用格式的函数重载 虚函数:冠以关键字 virtual 的成员函数称为虚函数,Object Oriented,二、联编的概念及分类 1、联编的概念 联编:源程序经过编译、联接成可执行文件的过程 即将可执行代码联编(装配)在一起的过程。 2、联编的分类: 静态联编(前期联编):在运行前完成的联编在编译时完成(要求在编译时就知道调用函数的全部信息)其优点是“效率高”。(重载函数使用静态联编。) 动态联编(后期联编):在运行时才完成的联编在程序运行时动态调用所需函数优点是提供了更好的“灵活性”、问题的“抽象性”、程序的“易维护性”。(switch 语句和 if 语句是动态联编的例子),Object Oriented,三、多态性的分类 编译时多态性:静态联编支持的多态性(静态多态性)通过函数重载及运算符重载实现。 运行时多态性:动态联编支持的多态性(动态多态性)通过虚函数实现。 四、函数重载 同一个类中的同名函数参数个数不一样、参数类型不一样、参数个数及类型不一样; 不同类中的同名函数通过类名调用或类的对象调用。 同一个类中同名的普通成员函数及常量成员函数通过const实现重载。,Object Oriented,第一节 虚函数和基类指针,冠以关键字 virtual 的成员函数称为虚函数 实现运行时多态的关键首先是要说明虚函数,另外,必须用基类指针调用派生类的不同实现版本 虚函数与派生类相结合,使C+能支持运行时多态性实现在基类中定义派生类所拥有的通用“接口”,而在派生类中定义具体的实现方法,即“一个接口,多种方法”。,Object Oriented,5-1,#include class Base public : Base(char xx) x = xx; void who() cout “Base class: “ x “n“ ; protected: char x; ; class First_d : public Base public : First_d(char xx, char yy):Base(xx) y = yy; void who() cout “First derived class: “ x “, “ y “n“ ; protected: char y; ; class Second_d : public First_d public : Second_d( char xx, char yy, char zz ) : First_d( xx, yy ) z = zz; void who() cout “Second derived class: “ x “, “ y “, “ z “n“ ; protected: char z; ;,Object Oriented,void main() Base B_obj( A ) ; First_d F_obj( T, O ) ; Second_d S_obj( E, N, D ) ; Base * p ; p = ,通过基类指针 只能访问从基类继承的成员,Object Oriented,5-2,#include class Base public : Base(char xx) x = xx; virtual void who() cout “Base class: “ x “n“ ; protected: char x; ; class First_d : public Base public : First_d(char xx, char yy):Base(xx) y = yy; void who() cout “First derived class: “ x “, “ y “n“ ; protected: char y; ; class Second_d : public First_d public : Second_d( char xx, char yy, char zz ) : First_d( xx, yy ) z = zz; void who() cout“Second derived class: “x“, “y“, “z“n“ ; protected: char z; ;,Object Oriented,void main() Base B_obj( A ) ; First_d F_obj( T, O ) ; Second_d S_obj( E, N, D ) ; Base * p ; p = ,由于who()的虚特性 随着p指向不同对象,执行不同实现版本,Object Oriented,注意: 一个虚函数,在派生类层界面相同的重载函数都保持虚特性 虚函数必须是类的成员函数,不能是全局函数和静态函数 不能将友员说明为虚函数,但虚函数可以是另一个类的友员 析构函数可以是虚函数,但构造函数不能是虚函数 动态联编只能通过指针或引用来操作虚函数,如果采用其他标识对象来操作虚函数,将采用静态联编方式调用虚函数。,Object Oriented,虚析构函数,构造函数不能是虚函数。建立一个派生类对象时,必须从类层次的根开始,沿着继承路径逐个调用基类的构造函数 析构函数可以是虚的。虚析构函数用于指引 delete 运算符正确析构动态对象,Object Oriented,5-3普通析构函数在删除动态派生类对象的调用情况,#include class A public: A() cout “A:A() is called.n“ ; ; class B : public A public: B() cout “B:B() is called.n“ ; ; void main() A *Ap = new B ;/用基类指针建立派生类的动态对象 B *Bp2 = new B ;/用派生类指针建立派生类的动态对象 cout “delete first object:n“ ; delete Ap;/析构由基类指针建立的派生类对象没有调用派生类构造函数问题? cout “delete second object:n“ ; delete Bp2 ;/析构由派生类指针建立的派生类对象正确调用派生类构造函数 ,Object Oriented,5-4虚析构函数在删除动态派生类对象的调用情况,#include class A public: virtual A() cout “A:A() is called.n“ ; ; class B : public A public: B() cout “B:B() is called.n“ ; ; void main() A *Ap = new B ; B *Bp2 = new B ; cout “delete first object:n“ ; delete Ap; cout “delete second object:n“ ; delete Bp2 ; ,定义了基类虚析构函数,基类指针指向的 派生类动态对象也可以正确地用delete析构 设计类层次结构时,提供一个虚析构函数, 能够使派生类对象在不同状态下正确调用析构函数,Object Oriented,第二节 纯虚函数和抽象类,纯虚函数是一个在基类中说明的虚函数,为各派生类提供一个公共界面,在基类中没有定义,要求任何派生类都定义自己的版本 纯虚函数 纯虚函数说明形式: virtual 类型 函数名(参数表)= 0 ; 一个具有纯虚函数的基类称为抽象类。,Object Oriented,class figure /figure.h protected : double x,y; 5-5 public: void set_dim(double i, double j=0) x = i ; y = j ; virtual void show_area() = 0 ; ; class triangle : public figure public : void show_area() cout“Triangle with high “x“ and base “y “ has an area of “x*0.5*y“n“; ; class square : public figure public: void show_area() cout“Square with dimension “x“*“y “ has an area of “x*y“n“; ; class circle : public figure public: void show_area() cout“Circle with radius “x; cout“ has an area of “3.14*x*x“n“; ;,Object Oriented,#include #include“figure.h“ void main() triangle t ; /派生类对象 square s ; circle c; t.set_dim(10.0,5.0) ; t.show_area(); s.set_dim(10.0,5.0) ; s.show_area() ; c.set_dim(9.0) ; c.show_area() ; ,抽象类至少有一个纯虚函数。 如果抽象类的一个派生类没有为继承的纯虚函数定义实现版本,则它仍然是抽象类。,Object Oriented,5-6,class point /*/ ; class shape ; / 抽象类 point center ; public : point where ( ) return center ; void move ( point p ) enter = p ; draw ( ) ; virtual void rotate ( int ) = 0 ; / 纯虚函数 virtual void draw ( ) = 0 ; / 纯虚函数 ; .,shape x ; / error,抽象类不能建立对象 shape *p ; / ok,可以声明抽象类的指针 shape f ( ) ; / error, 抽象类不能作为返回类型 void g ( shape ) ; / error, 抽象类不能作为参数类型 shape / ok,可以声明抽象类的引用,Object Oriented,class ab_circle : public shape int radius ; public : void rotate ( int ) ; ;,ab_circle 类仍为抽象类 ab_circle : draw ( ) 、ab_circle : rotate ( ) 也是纯虚函数,要使 ab_circle 成为非抽象类, 必须作以下说明: class ab_circle : public shape int radius ; public : void rotate ( int ) ; void draw ( ) ; ; 并提供 ab_circle : draw ( ) 和 ab_circle : rotate ( int ) 的定义,Object Oriented,5-7声明抽象类指针,#include #include“figure.h“ void main() figure *p; / 声明抽象类指针 triangle t; square s; circle c; p= ,Object Oriented,5-8抽象类引用,#include class Number public : Number (int i) val = i ; virtual void Show() = 0 ; protected: int val ; ; class Hex_type : public Number public: Hex_type(int i) : Number(i) void Show() cout “Hexadecimal:“ hex val endl ; ; class Dec_type : public Number public: Dec_type(int i) : Number(i) void Show() cout “Decimal: “ dec val endl ; ; class Oct_type : public Number public: Oct_type(int i) : Number(i) void Show() cout “Octal: “ oct val endl ; ;,Object Oriented,void fun( Number / Oct_type:Show() ,Object Oriented,应用举例求圆、圆的内切正方形及外切正方形的面积及周长 #include #include class shape protected : double r; public: shape(double x) r=x; virtual double area()=0; virtual double perimeter()=0; ;,Object Oriented,class circle:public shape public: circle(double x):shape(x) double area() return 3.14*r*r; double perimeter() return 2*3.14*r; ; class in_square:public shape public: in_square(double x):shape(x) double area() return 2*r*r; double perimeter() return 4*sqrt(2)*r; ;,Object Oriented,class ex_square:public shape public: ex_square(double x):shape(x) double area() return 4*r*r; double perimeter() return 8*r; ; void main() shape *p; circle ob1(5.0); in_square ob2(5.0); ex_square ob3(5); p=,Object Oriented,第三节 运算符重载,运算符重载使得用户自定义的数据以一种更简洁的方式工作,就是赋予已有的运算符多重含义。,例如 int x , y ; y = x + y ;,matrix m1 , m2 ; / 矩阵类对象 m2 = Madd ( m1 , m2 ) ; / 调用函数计算两个矩阵的和,complex c1 , c2 ; / 复数类对象 c1 = Cadd (c1 , c2 ) ; / 调用函数计算两个复数的和,能表示为 c1 = c1 + c2 ; ?,能表示为 m1 = m1 + m2 ; ?,定义 运算符重载函数,Object Oriented,类以外的运算符重载,#include class complex public : double real ; double imag; complex(double r=0,double i=0) real=r;imag=i; ; complex operator+(complex co1,complex co2)/运算符“+”的重载函数 complex temp; temp.real=co1.real+co2.real; temp.imag=co1.imag+co2.imag; return temp; void main() complex com1(1.1,2.2),com2(3.3,4.4),total1,total2; total1=operator+(com1,com2);/运算符重载的使用方法1 cout “real1=“total1.real; cout“ imag1=“total1.imagendl; total2=com1+com2;/运算符重载的使用方法2 cout “real2=“total2.real; cout“ imag2=“total2.imagendl; ,Object Oriented,一、运算符重载的实质 运算符重载是对已有的运算符赋予多重含义 必要性 C+中预定义的运算符其运算对象只能是基本数据类型,而不适用于用户自定义类型(如类) 实现机制 将指定的运算表达式转化为对运算符函数的调用,运算对象转化为运算符函数的实参。 相当于a+b = +(a,b) 编译系统对重载运算符的选择,遵循函数重载的选择原则。 相当于选+(1,2)还是+(1,1),(2,2)?,Object Oriented,二、重载运算符的限制 1、不能重载的算符 . : * ?: # sizeof 2、重载运算符可以对运算符作出新的解释,但原有基本语义不变: 不改变运算符的优先级和结合性。(否则难以记忆) 不改变运算符所需要的操作数,即单目运算符只能重载为单目运算符,不能将单目运算符重载为双目运算符。 不能创建新的运算符,只有系统预定义的运算符才能被重载。 经重载的运算符,其操作数中至少应该有一个是自定义类型。 (否则系统已经实现了) 3、运算符通常是对类中的私有成员进行操作,故重载运算符应能访问类中的私有成员,所以重载运算符一般采用成员函数或友员函数的形式,Object Oriented,三、重载为类成员函数 语法形式为: 类型 类名 : operator op ( 参数表 ) / 相对于该类定义的操作 其中,当为双目运算符时,参数表中为一个参数,单目运算符时,参数表为空通过this指针传递。,Object Oriented,(一)双目运算符的重载 例【5.3.2】重载二个复数对象的加、减、乘、除运算符熟悉双目运算符的重载。 1、分析:设两个复数a+bi和c+di,则有: 加法:(a+bi)+(c+di)=(a+c)+(b+d)i; 减法:(a+bi)-(c+di)=(a-c)+(b-d)i; 乘法:(a+bi)*(c+di)=(ac-bd)+(ad+bc)i 除法:(a+bi)/(c+di)=(a+bi)*(c-di)/(c2+d2) =(ac+bd)/ (c2+d2)+(bc-ad)i/(c2+d2) 2、程序:,Object Oriented,#include class complex private : double real ; double imag; public : complex(double r=0,double i=0) real=r;imag=i; complex operator+(complex c); complex operator-(complex c); complex operator*(complex c); complex operator/(complex c); void print(); ;,Object Oriented,complex complex :operator+(complex c)/重载“+” complex temp; temp.real=real+c.real; temp.imag=imag+c.imag; return temp; complex complex :operator-(complex c)/重载“-” complex temp; temp.real=real-c.real; temp.imag=imag-c.imag; return temp; ,Object Oriented,complex complex :operator*(complex c)/重载“*” complex temp; temp.real=real*c.real-imag*c.imag; temp.imag=real*c.imag+imag*c.real; return temp; complex complex :operator/(complex c)/重载“/” complex temp; double t; t=c.real*c.real+c.imag*c.imag; temp.real=(real*c.real+imag*c.imag)/t; temp.imag=(c.real*imag-real*c.imag)/t; return temp; ,Object Oriented,void complex:print() cout 0) cout“+“; if (imag!=0) cout imag“i“endl; void main() complex A1(2.3,4.6),A2(3.6,2.8),A3,A4,A5,A6; A3=A1+A2;A4=A1-A2; A5=A1*A2;A6=A1/A2; A1.print();A2.print(); A3.print();A4.print(); A5.print();A6.print(); ,Object Oriented,(二)单目运算符重载(单目运算符重载时没有参数。) 前置和后置,函数名都是operator +,所以人为给后置多加一个哑参数,只有类型名。 例【5.3.3】运算符前置+和后置+重载为时钟类的成员函数。 前置单目运算符,重载函数没有形参,对于后置单目运算符,重载函数需要有一个整型形参。 操作数是时钟类的对象。 实现时间增加1秒钟。,Object Oriented,#include class Clock /时钟类声明 public: /外部接口 Clock(int NewH=0, int NewM=0, int NewS=0) Hour=NewH;Minute=NewM;Second=NewS; void ShowTime() coutHour“:“Minute“:“Secondendl; void operator +(); /前置单目运算符重载 void operator +(int); /后置单目运算符重载 private: /私有数据成员 int Hour, Minute, Second; ;,Object Oriented,void Clock:operator +( ) /前置单目运算符重载函数 Second+; if(Second=60) /考虑进位 Second=Second-60; Minute+; if(Minute=60) Minute=Minute-60; Hour+; Hour=Hour%24; cout“+Clock: “; ,Object Oriented,void Clock:operator +(int) /后置单目运算符重载 Second+; if(Second=60) Second=Second-60; Minute+; if(Minute=60) Minute=Minute-60; Hour+; Hour=Hour%24; cout“Clock+: “; ,Object Oriented,void main() Clock myClock(23,59,59); cout“First time output:“; myClock.ShowTime(); myClock+; myClock.ShowTime(); +myClock; myClock.ShowTime(); ,Object Oriented,四、重载为友元函数 例【5.3.4】将+、-(双目)重载为复数类的友元函数。 两个操作数都是复数类的对象。 #include class complex private : double real ; double imag; public : complex(double r=0,double i=0) real=r;imag=i; void print(); friend complex operator+(complex a,complex b); friend complex operator-(complex a,complex b); friend complex operator*(complex a,complex b); friend complex operator/(complex a,complex b); ;,Object Oriented,complex operator+(complex a,complex b) complex temp; temp.real=a.real+b.real; temp.imag=a.imag+b.imag; return temp; complex operator-(complex a,complex b) complex temp; temp.real=a.real-b.real; temp.imag=a.imag-b.imag; return temp; ,Object Oriented,complex operator*(complex a,complex b) complex temp; temp.real=a.real*b.real-a.imag*b.imag; temp.imag=a.real*b.imag+a.imag*b.real; return temp; complex operator/(complex a,complex b) complex temp; double t; t=b.real*b.real+b.imag*b.imag; temp.real=(a.real*b.real+a.imag*b.imag)/t; temp.imag=(b.real*a.imag-a.real*b.imag)/t; return temp; ,Object Oriented,void complex:print() cout 0) cout“+“; if (imag!=0) cout imag“i“endl; void main() complex A1(2.3,4.6),A2(3.6,2.8),A3,A4,A5,A6; A3=A1+A2; A4=A1-A2; A5=A1*A2; A6=A1/A2; A1.print(); A2.print(); A3.print(); A4.print(); A5.print(); A6.print(); ,Object Oriented,重载为成员函数,解释为: Object . operator op () 操作数由对象Object通过this指针隐含传递 重载为友员函数,解释为: operator op (Object) 操作数由参数表的参数Object提供,1一元运算符,Object op 或 op Object,Object Oriented,重载为成员函数,解释为: ObjectL . operator op ( ObjectR ) 左操作数由ObjectL通过this指针传递,右操作数由参数ObjectR传递 重载为友员函数,解释为: operator op ( ObjectL, ObjectR ) 左右操作数都由参数传递,2二元运算符,ObjectL op ObjectR,Object Oriented,总结 运算符函数可以重载为成员函数或友员函数 关键区别在于成员函数具有 this 指针,友员函数没有this指针 不管是成员函数还是友员函数重载,运算符的使用方法相同。但传递参数的方法不同,实现代码不同,应用场合也不同。 当一元运算符的操作数,或者二元运算符的左操作数是该类的一个对象时,定义重载运算符函数为成员函数 友员函数重载运算符常用于算符的左右操作数类型不同的情况,左操作数可以是常数或其他类型的数。 运算符=、( )、 、-不能用友元函数重载,(只能用成员函数重载),Object Oriented,class nclass private : int a ; int b ; public : nclass operator+(int x); ; nclass nclass : operator+(int x) nclass temp ; temp.a=a+x; temp.b=b+x; return temp; ,void main() nclass ob1,ob2; ob2=ob1+100; ob2=100+ob1; ,程序中: ob2=ob1+100;正确 ob2=100+ob1;不正确,为什么?,例【5.3.5】常数与复数相加。 #include class complex private : double real ; double imag; public : complex(double r=0,double i=0) real=r;imag=i; void show() cout “real=“real“ imag=“imagendl; friend complex operator+(complex co,double x); friend complex operator+(double x,complex co); ;,Object Oriented,complex operator+(complex co,double x) complex temp; temp.real=co.real+x; temp.imag=co.imag; return temp; complex operator+(double x,complex co) complex temp; temp.real=x+co.real; temp.imag=co.imag; return temp; void main() complex com1(1.1,2.2),com2,com3; com2=com1+10.0; com2.show(); com3=20.0+com1; com3.show(); ,Object Oriented,五、赋值运算符“=”的重载 同拷贝构造函数一样,通常“=”不用重载,同一类的对象可直接赋值。如:ob1=ob2; 当在类中用new分配内存空间,在析构函数中用delete中释放内存空间时,应重载“=”运算符。,例【5.3.6】调试下列程序,分析出错的原因,#include #include class string char *ptr; public : string(char *s) ptr=new charstrlen(s)+1; strcpy(ptr,s); string() delete ptr; void print() cout ptrendl; ;,void main() string p1(“chen“); string p2(“ “); p2=p1; cout “p2: “; p2.print(); cout“p1: “; p1.print(); ,Object Oriented,void main() string p1(“chen“); string p2(“ “); p2=p1; cout “p2: “; p2.print(); cout“p1: “; p1.print(); ,Object Oriented,出错原因分析:,Object Oriented,解决办法:重载“=”运算符 例【5.3.7】将上例程序改为:,#include #include class string char *ptr; public : string(char *s) ptr=new charstrlen(s)+1; strcpy(ptr,s); string() delete ptr; void print() cout ptrendl; string ,Object Oriented,string ,说明: 类的赋值运算符“=”只能重载为成员函数,重载后不能被继承。,Object Oriented,注意:对象初始化时的赋值和已创建对象之间的赋值虽然都涉及对象的复制,但它们是两个不同的操作。对象初始化首先是为新对象分配存储空间,然后执行对象复制。 如:Point p1, p2(3.14, 4.06); Point p3=p2; /调用拷贝构造初始化函数 p1=p2; /调用赋值运算符重载,Object Oriented,本章小结,多态: 同样的消息被不同类型的对象接收时导致完全不同的行为,是对类的特定成员函数的再抽象。 运算符重载 对已有的运算符赋予多重含义,使用已有运算符对用户自定义类型(比如类)进行运算操作。 联编 程序自身彼此关联的过程称为联编,联编确定程序中的操作调用与执行该操作的代码间的关系。 静态联编工作出现在编译阶段。 动态联编工作在程序运行时执行。虚函数是动态联编的基础。,Object Oriented,纯虚函数 在基类中说明的虚函数,它在该基类中可以不给出函数体,要求各派生类根据实际需要编写自己的函数体。 抽象类 带有纯虚函数的类是抽象类。 抽象类的主要作用是通过它为一个类族建立一个公共的接口,使它们能够更有效地发挥多态特性。,Object Oriented,练习,1、分别使用成员函数和友员函数编程序重载运算符“+”,使该运算符能实现两个字符串的连接。,Object Oriented,#include“iostream.h“ #include class string public: string() *str = 0; string( char *pstr ) strcpy( str,pstr ); char *gets() return str; string operator+( string obj ); private: char str100; ; string string:operator+( string obj ) strcat( str,obj.str ); return str; /或return *this void main() string obj1( “Visual“ ),obj2( “ C+“ ),obj3; obj3 = obj1 + obj2; cout obj3.gets() endl; ,Object Oriented,#include #include class string public: string() *str= 0; string( char *pstr ) strcpy( str,pstr ); char *gets() return str; friend string operator+( string obj1,string obj2 ); private: char str100; ; string operator+( string obj1,string obj2 ) string tempobj; strcat( tempobj.str,obj1.str ); strcat( tempobj.str,obj2.str ); return tempobj; void main() string obj1( “Visual“ ),obj2( “ C+“ ),obj3; obj3 = obj1 + obj2; cout obj3.gets() endl; ,Object Oriented,Employee,抽象类 提供一般属性,共同操作界面,管理人员类 提供特殊属性,操作实现,计时工人类 提供特殊属性,操作实现,计件工人类 提供特殊属性,操作实现,2.计算雇员工资,Object Oriented,class Employee public: Employee(long no, char* na); virtual Employee(); /虚析构函数 char * getName(); long getNumber(); virtual double earnings() =0; /纯虚函数,计算月薪 virtual void print(); /虚函数,输出编号、姓名 protected: long number; / 编号 char * name; / 姓名 ;,Object Oriented,3、异质链表 程序中,用基类类型指针,可以生成一个连接不同派生类对象的动态链表,即每个结点指针可以指向类层次中不同的派生类对象。 这种结点类型不相同链表称为异质链表。,Object Oriented,class Employee public: Employee(long no, char* na); virtual Employee(); /虚析构函数 char * getName(); long getNumber(); virtual double earnings() =0; /纯虚函数,计算月薪 virtual void print(); /虚函数,输出编号、姓名 Employee *next ; protected: long number; / 编号 char * name; / 姓名 ;,Object Oriented,void AddFront( Employee * ,Object Oriented,for 1:,#include #include class Point public: Point(double xi, double yi) X = xi ; Y = yi ; double GetX() return X ; double GetY() return Y ; friend double Distance ( Point ,Object Oriented,for 2:类和对象,定义一个正方形类,该类包括: (1)受保护类数据成员,表示正方形类的边长,取值范围在1-30 (2)四个成员函数,分别为: 带参构造函数,初始化正方形边长; 取边长函数GetLen( ); 设置边长函数 SetLen( ),重新设置边长,并检查是否在规定范围内; 画正方形函数 DrawSquare ( ),用边长做为行数和每行输出个数,输出“*”; (3) 主函数:创建一个边长为5的正方形;输出正方形,由键盘修改边长为8;重新输出正方形。,Object Oriented,for 3:继承和派生,设计两个类,一个类描述点,另一个类描述圆。圆由圆心和半径构成,圆类由点类派生而来,圆心的特性描述由点类继承下来。要求圆类提供: (1)求圆面积的成员函数 (2) 取圆心坐标的两个函数 Get_X( )和Get_Y( ) (3) 支持初始化的带参构造函数 (4) 主函数,键盘输入圆心坐标 x,y, 以及半径 r, 输出圆面积。,Object Oriented,for 4:继承和派生,一个图形是由一个圆和一个矩形构成,要求求解图形的面积。设计3个类,其中两个是基类,一个基类描述圆,另一个基类描述矩形,第三个派生类是由一个圆和一个矩形构成的图形类。圆类包含数据成员半径和求圆面积的成员函数,矩形类包含数据成员长和宽、求矩形面积的成员函数。派生的图形类提供输出面积的函数及实现初始化的带参构造函数。 (圆半径 r=10, 矩形 长=20, 宽=50,输出面积),Object Oriented,for 5:虚函数,编一个程序计算正方体,球体和圆柱体的表面积和体积。 要求:抽象出一个公共基类container为抽象类,在其中定义求表面积和体积的纯虚函数。抽象类中定义一个公共的数据成员radius,此数值可以作为球体的半径、正方体的边长、圆柱体底面圆半径。由该抽象类派生出的三个类,都有求表面积和体积的实际定义。键盘输入radius的值后,可以输出这3种立方体的面积。,Object Oriented,for 6:函数重载,设计一个用来表示直角坐标系上点的位置的Location类,然后在主程序中创建两个对象A和 B,要求A在第三象限,B在第二象限,计算给定两点之间的距离并按如下格式输出结果: A(x1,y1),B(x2,y2) Distance=d 其中x1,y1,x2,y2为指定值,d为计算结果。,Object Oriented,for7 类的应用,一圆型游泳池如图所示,现在需在其周围建一圆型过道,并在其四周围上栅栏。栅栏价格为35元/米,过道造价为20元/平方米。过道宽度为3米,游泳池半径由键盘输入。要求编程计算并输出过道和栅栏的造价。,Object Oriented,复习,结构类型用struct定义,是用户自定义数据类型,由不同类型的数据成员组成。结构变量在内存占有一片连续的存储区间。结构变量成员用圆点运算符和箭头运算符访问。 类类型是结构类型的拓展,通常用关键字class定义。类是数据成员和成员函数的封装。类的实例称为对象。 数据成员是类的属性,可以为各种合法的C+类型,包括类类型。成员函数用于操作类的数据或在对象之间发送消息。 类成员由private, protected, public决定访问特性。public成员集称为类的接口。不能在类的外部访问private成员。 构造函数是特殊的成员函数,在创建和初始化对象时自动调用。析构函数则在对象作用域结束时自动调用。,Object Oriented,静态成员是局部于类的成员,它提供一种同类对象的共享机制。静态数据成员在编译时建立并初始化存储空间。静态数据成员和静态成员函数依赖于类而使用,与是否建立对象无关。 友员是类对象操作的一种辅助手段。一个类的友员可以访问该类各种性质的成员。 从编译器的观点看,类是一个程序包。定义什么类成员和如何声明成员的访问性质,取决于问题的需要。,Object Oriented,继承是面向对象程序设计实现软件重用的重要方法。程序员可以在已有类的基础上定义新的数据成员和成员函数。原有类称为基类,新的类称为派生类,这种程序设计方法称为继承。 派生类成员由基类成员和自身定义的成员组成。单继承的派生类只有一个基类。多继承的派生类有多个基类。 对基类成员的访问性质受继承方式影响。 公有(public)继承方式,基类的public和protected成员在派生类中性质不变; 保护(protected)继承,基类的public和protected成员都成为派生类的protected成员; 私有(private)继承,基类的public和protected成员都成为派生类的private成员。,Object Oriented,派生类中不可见基类的私有数据成员,但这些数据存储单元依然被建立。创建派生类对象时,派生类的构造函数总是先调用基类构造函数来初始化派生类中的基类成员。调用基类构造函数可以通过初始化列表实现数据成员的初始化。调用析构函数的次序和调用构造函数的次序相反。 类继承关系中,覆盖成员出现访问的二义性,可以用作用域符显示指定类成员。 为了避免多继承类格中的汇点类在派生类对象中产生不同副本,C+提供虚继承机制。 多继承提供了软件重用的强大功能,也增加了程序的复杂性。,Object Oriented,虚函数和多态性使软件设计易于扩充。 冠以关键字virtual的成员函数称为虚函数。派生类可以重载基类的虚函数,只要接口相同,函数的虚特性不变。 基类指针可以指向派生类对象;以及基类中拥有虚函数,是支持多态性的前提。当通过基类指针或引用使用虚函数时,C+在程序运行时根据所指对象类型在类层次中正确选择重定义的函数。这种运行时的晚期匹配称为动态联编。 如果通过对象名和点运算符方式调用虚函数,则调用关联在编译时由引用对象的类型确定,称为静态联编。 如果一个基类中包含虚函数,通常把它的析构函数说明为虚析构函数。这样,它的所有派生类析构函数也自动成为虚析构函数(即使它们与基类析构函数名字不相同)。虚析构函数使得用delete算符删除对象时,系统可以正确地调用析构函数。,Object Oriented,纯虚函数是在说明时代码“初始化值”为0的虚函数。纯虚函数本身没有实现,由它的派生类定义实现版本。 具有纯虚函数的类称为抽象类。抽象类只能作为基类,不能建立实例化对象。如果抽象类的派生类不提供纯虚函数的实现,则它依然是抽象类。定义了纯虚函数实现的派生类,即可以建立对象的类称为具体类。 尽管不能建立抽象类对象,但抽象类机制提供的软件抽象和可扩展性的手段;抽象类指针使得派生的具体类对象具有多态操作能力。异质链表是多态应用的一个实例。,Object Oriented,运算符重载的作用是令用户可以像操作基本数据类型一样,用简洁明确的运算符操作
展开阅读全文
相关资源
相关搜索

当前位置:首页 > 图纸专区 > 课件教案


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!