已阅读5页,还剩16页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第8章 继承与派生 8-1. 教学目的与要求1理解继承的概念;2掌握继承的实现方法;3继承中常见问题的处理方法。 8-2. 主要内容及重点:类是C+中进行数据封装的逻辑单位。继承是面向对象程序设计的一个重要特征之一,它允许在既有类的基础上创建新的类,新类可以从一个或多个既有类中继承操作和数据,而且可以重新定义或加进新的数据和操作,从而形成类的层次或等级。既有类称为基类或父类,在它基础上建立的新类称为派生类、导出类或子类。本章的重点是派生类的定义和使用、创建派生类对象时构造函数的调用顺序、多重继承中的冲突及其消除方法以及作用域运算符的几种使用方法等。本章的难点是基类的初始化、多重继承中的冲突以及虚基类等。8-3. 第8章 继承-课件 3-4. 8-4. 第8章 继承-复习总结 继承是面向对象程序设计方法的基本特性之一,继承可以提高软件的重要性。 本章主要介绍了C+中的继承性的实现方法以及在继承性常见问题的处理方法。包括基类的初始化、访问类型的调整、冲突及其消除方法、成员覆盖、赋值兼容性以及虚基类等。 类的派生包括三种类型:私有派生、保护派生、公有派生。利用构造函数的初始化成员列表,可以在派生类中对基类成员进行初始化。在继承层次关系中要避免冲突的产生,通常是采用指定作用域和定义虚基类这两种方法来解决问题。8-5. 第8章 继承-练习 8-5-1.思考题:1).派生类有几种方式,每种方式中派生类对基类成员的继承如何? 2). 在创建派生类对象时,构造函数的执行次序是怎样的?析构函数的执行次序是怎样的?3). 派生类对象如何对基类中的成员进行初始化?4). 在多重继承中,在什么情况下会产生冲突?如何消除冲突?5). 列举我们已学习的作用域运算符“:”的所有用途。6). 属于不同类的对象在什么情况下可以互相赋值?7).什么叫虚基类?为什么要引进虚基类?8-5-2.练习题: 课后练习题见练习单元。第8章 继承与派生类是C+中进行数据封装的逻辑单位。继承是面向对象程序设计的一个重要特征之一,它允许在既有类的基础上创建新的类,新类可以从一个或多个既有类中继承操作和数据,而且可以重新定义或加进新的数据和操作,从而形成类的层次或等级。既有类称为基类或父类,在它基础上建立的新类称为派生类、导出类或子类。8 .5 虚基类 8 .51 虚基类的概念对于直接继承,一个基类只能被派生类继承一次;对于间接继承,一个基类可以被派生类继承多次。如图所示的继承结构中,基类A在类D中会产生两个副本。这时如果在D类中使用从A类继承的成员时,如果不指定其作用域,会出现同名冲突。 虚基类的基本思想是:将一个基类声明为虚基类时,不管它在派生类中被继承多少次,该基类中的成员在该派生类中始终只有一个副本,如图。类D类C类B类A图 虚基类的类层次 虚基类是通过关键字virtual实现的,定义虚基类的格式为:class :virtual ,-,virtualaccesss - ;或class:virtual ,-,virtual- ;例1:使用虚基类,使派生类中只有基类一个副本。# include class CFurniture protected:int weight ;public:CFurniture( ) void SetWeight (int i ) weight=i ;int GetWeight ( ) return weight ;cout”sleeping -n ;class CBed:virtual public CFurniture /A 定义虚基类public :CBed ( ) void sleep ( ) ;class CSofa:virtual public CFurniture /B 定义虚基类 public:CSofa ( ) void WatchTV() cout”Watch TV . n “ ; ;class CSleepSofa :public CBad ,public Csofa public : CSleepSofa ( ) void FoldOut ( ) cout”Fold out the sofa 。 n ” ; ;void main ()CSleepSofa ss ;ss.SetWeight (20) ; /Ccoutss.GetWeight( )n ; /D执行结果:20例 /program 8-6.cpp p269#include class A public:int i;void showa()couti=iendl;class B: virtual public A /对类A进行了虚拟继承public:int j; class C: virtual public A /对类A进行了虚拟继承public:int k;class D : public B, public C /派生类D的二基类B、C具有共同的基类A,但采用了虚拟继承/从而使类D的对象中只包含着类A的1个实例public:int n;void showall()couti,j,k,n=i “ ,”j “ ,”k “ ,”nendl; void main() D Dobj; /说明D类对象Dobj.i=11; /若非虚拟继承时会出错! / - 因为“D:a”具有二义性Dobj.j=22; Dobj.k=33; Dobj.n =44; Dobj.showa(); /若非虚拟继承时会出错! / - 因为“D:showa”具有二义性Dobj.showall(); 程序执行后的显示结果如下:/*i=11i,j,k,n=11 ,22 ,33 ,44Press any key to continue*/8 .52 虚基类的初始化虚基类的初始化与一般的多重继承的初始化在语法上是一致的,但构造函数的调用次序有不同。1虚基类的构造函数在非虚基类的构造函数之前调用。如下例的B行2若同一层次中包含多个虚基类,这些虚基类的构造函数按它们的说明次序调用。3若虚基类由非虚基类派生而来,则仍然先调用基类的构造函数,再调用派生类的构造函数,如下例的A行。类D类C类B类A图 虚基类的类层次4对图的类层次结构,由于此时虚基类A在类D中只有一个副本,因此在创建D的对象时,无法确定是通过类B还是通过类C调用A的构造函数,为了解决这个矛盾,C+规定在这种情况下可以在类D中,直接调用类A的构造函数。即在D类的构造函数的初始化成员列表中,不仅要调用类B和类C的构造函数,还必须调用类A的构造函数而且是最先调用。因为在类D只有A的一个版本,所以调用类B和类C的构造函数时不再重复调用类A的构造函数了,即类A的构造函数只运行一次。下面通过一个例子来说明这一个问题。例1 虚基类的构造函数的调用次序# include class CBase1public:CBase1 ( )cout”This is CBase1 class! n “ ;class CBase2public:CBase2 ( ) cout”This is CBase2 class ! n “ ;class CDerive1:public CBase2 ,virtual public CBase1 /Apublic:CDerive1( )cout”This is CDerive1 class ! n “ ;class CDerive2:public CBase2 ,virtual public CBase1 /Apublic:CDerive2 ( )cout”This is CDerive2 class ! n “ ;class CTop:public CDerive1 ,virtual public CDerive2 /B虚基类 虚基类 CBase2 CBase2 CBase1 CTop CDerive2 CDerive1 public: CTop ( )cout”This is CTop class ! n “ ;void main ( ) CTop topObj ; 执行结果:This is CBase1 class !This is CBase2 class !This is CDerive2 class !This is CBase2 class !This is CDerive1 class !This is CTop class !类D类C类B类A图 虚基类的类层次例2 初始化虚基类成员 # include class CBaseint x ,y ;public:CBase ( int a , int b )x=a , y=b ;show ( )coutxtyendl ;class CDerive1:virtual public CBase /A声明CBase为虚基类public:CDerive1( ):CBase(2,3) ;class CDerive2:virtual public CBase /B声明CBase为虚基类public:CDerive2 ( ):CBase (4 ,5) ;class CTop :public CDerive1,public CDerive2public: CTop ( ):CBase (6 , 7 ) /C直接调用虚基类CBase的构造函数, /如果A、B行没有声明CBase为虚基类,则不可这样使用。 ;void main ( )CTop topObj ;topObj.show() ;执行结果;6 78. 6 多态性与虚函数多态性是面向对象系统中的又一重要的概念。本节主要介绍C+中实现运行时的多态性的方法虚函数。多态性:就是当不同对象接受到相同消息时能产生不同的动作。8. 6.1函数重载与静态联编C+中有两种编译方式:“早期联编”和“滞后联编”。都支持多态性。函数名重载或运算符重载前面已经讨论过,通过函数名重载或运算符重载来实现的是编译时的多态性。也叫“早期联编”或“静态联编”。“早期联编”(也称“静态联编”):指系统在编译时就决定如何实现某一动作。是系统默认的编译方式。 具有执行速度快的优点(因为在执行之前,编译系统能进行代码的优化)。8. 6.2函数超载、虚函数、动态联编8. 6.2.1 函数超载 函数超载:即C+允许在不同的类中出现其原型完全相同的函数。 (1)允许(支持)多个不同的函数(的实现)使用完全相同的函数名、函数参数表以及函数返回类型。 (2)仅在基类与其派生类的范围内实现(与使用)。 (3)通常这些函数是语义相近的或完全相同的(仅具体实现方法即实现代码不同)。8. 6.2.2 “动态联编”“动态联编”(也称“滞后联编”):是指系统在运行时动态实现某一动作。要实现动态连接往往要采用一些特定的机制通知编译系统。具有灵活和高层问题抽象的优点。运行时的多态性:是指在程序运行过程中,根据具体的执行环境来动态地确定。是通过类的继承关系和虚函数来实现的。8. 6.2.3 虚函数虚函数是在引入派生类概念后,用来表现基类和派生类的成员函数之间的一种关系。(1)虚函数是一种特殊的成员函数(非静态) ,在定义某一基类(或派生类)时,将其中的某一个非静态成员函数的属性说明为virtual,则称该函数为虚函数。虚函数的一般格式为: virtual 成员函数() . . . . . . ;(2) 虚函数通常为基类中的成员函数,且当基类的某个成员函数定义为虚函数时,它的所有派生类中与虚函数相同的函数(返回类型、函数名、参数个数、参数类型和顺序都相同,以下同)都为虚函数,不管它们前面有没有冠以virtual,即在派生类中这类函数前可以加也可以不加virtual,它们可以通过继承关系隐式地定义为虚函数。即虚函数的使用与函数超载密切相关。(3)当基类中的某个成员函数被定义为虚函数时,通常情况下,在其派生类中要对该函数重新定义,即定义一个与该函数相同的函数,否则该虚函数将不能发挥其应有的作用。(4)虚函数的作用:当编译器编译虚函数时,编译系统将用动态连接的方式进行编译。即在编译时不确定该虚函数的版本,而是利用一种机制(虚函数表),在运行过程根据其所指向的实例决定使用哪一个函数版本。(5)使用虚函数时要注意以下几点:1)虚函数必须是类的一个成员函数,但不能是静态的成员函数。2)若要实现这种类型的多态性,必须使用基类的指针或引用。 即只有将该基类指针或引用指向它的任一派生类,并通过该指针或引用调用虚函数,才能实现动态多态性。如果将派生类的实例用赋值语句赋给其基类实例,即使调用虚函数,也不能实现动态多态。3)若虚函数为外联函数,则在外面定义函数体时,在函数名前不要加virtual。4)通过域操作符“:”可以抑制虚函数调用。比如,若将下例1中的D行改为: p-CStudent:Calctuition(); 则该行输出为:得到本科生学费计算结果!5)虚函数是通过内部虚函数表机制来实现动态多态的。 由于函数调用作为索引被映射到虚函数表中,然后在表中找到调用函数的地址,因此,虚函数的执行时间稍长一些,另外,要为虚函数表申请额外的内存空间。所以,在将一个函数声明为虚函数时要经过慎重的考虑和权衡,不要因为它能实现动态多态而将所有函数声明为虚函数。如下例1中a在编译时,扫描到p-Calctuition(),首先检查Calctuition()是否为虚函数。b若是虚函数,则仅把与Calctuition()同原型的虚函数的地址信息列表待查。c在程序运行阶段,当程序执行到表达式p-Calctuition()时,根据指针当前所指向的对象的类属,来决定这时的Calctuition()应执行哪个类中的哪个Calctuition(),从而决定执行哪个函数体。在一个派生类中重新定义基类的虚函数是函数重载的另一种特殊形式,但不同于一般的函数重载。二者的区别:-6)如果各虚函数有什么不同,系统会根据不同情况分别处理。有下面两种情况:仅返回类型不同,其余均相同,系统当出错处理。函数原型不同,仅函数名相同。此时,系统会将它认为是一般的函数重载。 此时,该函数没有能通过继承关系隐式地定义为虚函数,因此对该函数的调用不具有动态多态性。7)在创建派生类的对象时,首先调用基类的构造函数,如果此时基类的构造函数中调用虚函数,则它应该调用虚函数的基类版本。8)构造函数不能为虚函数,但析构函数可以。9) 利用虚析构函数的一般原则是:当将基类指针或引用用new运算符指向派生类实例时,为了释放派生类实例时能调用派生类的析构函数,必须将基类的析构函数定义为虚函数。8. 6.3 纯虚函数与抽象基类有时基类往往表示一些抽象的概念,它的成员函数没什么实际意思,此时可将它定义为一个抽象类。(1)抽象类的作用是: 在由该类派生出来的类体系中,它可对类体系中的任何一个子类提供一个统一的接口,即用相同的方法对该类体系中的任一子类实例进行各种操作,并可把接口和实现分开。在Visual C+的基础类库中正是使用了这种技术。(2)对于抽象类的使用有以下几点规定:1)抽象类只能用做其他类的基类,不能建立抽象实例。2)抽象类不能用做参数类型、函数返回类型或显式类型转换。3)可以声明抽象类的指针或引用,此指针或引用可以指向它的派生类,进而实现多态性。(3)C+中不能直接定义抽象类,必须通过如下两种方法间接定义抽象类: 一种方法是:将该类中的所有构造函数都声明为私有类型或受保护类型,这样该类不能有自己的对象;另一种方法是:在该类中定义“纯虚函数”。这样所属的类就为抽象类。(4)定义纯虚函数的一般格式:virtual 成员函数()=0 ;例如:class CAbstrabct . . . . . . public: virtual void GetData (int)=0 ; /纯虚函数 . . . . . .(5)关于纯虚函数的定义和使用的几点说明:1) 定义纯虚函数时,不能定义虚函数的实现部分。因此在对纯虚函数重新定义之前,不能调用该函数。2)虚函数的函数名赋值0并没有特别的含义,只是表明该虚函数为纯虚函数。 它与定义空函数不一样,空函数的函数体为空,即调用该函数时,不执行任何操作。3)在定义具有纯虚函数的类(抽象类)的派生类时,必须对纯虚函数重新定义,否则该派生类还是抽象类,不能有自己的实例。4)当创建具有纯虚函数的抽象类的指针时,该指针不能调用抽象类中的纯虚函数,但可以调用抽象类中的非纯虚函数。8. 7 虚函数使用实例(8. 6 多态性与虚函数) 例例1虚函数示例#includeclass Cstudent /本科生类/-public: void Calctuition() /计算机本科生学费 cout”得到本科生学费计算结果! ”endl; /Avirtual void Calctuition() /计算机本科生学费 cout”得到本科生学费计算结果! ”endl; /A/-;class CGraduteStudent :public Cstudent /研究生类,它是本科生类的派生类/-public:void Calctuition () cout”得到研究生学费计算结果!”Calctuition();p=&s2 ; /C 此时p指向s2;p-Calctuition(); /D 但所调用的函数仍然是基类的。s2.Calctution (); 执行结果:得到本科生学费计算结果!得到本科生学费计算结果!得到研究生学费计算结果!将上例A段改为:virtual void Calctuition() 即将该成员函数声明为虚函数后,则编译到B行时,将实例*p中的成员函数Calctuition()按动态连接的方式进行编译,则在运行过程中,当在C行将p指向s2后,在D行中调用的函数是派生类的版本。此时执行结果为:/得到本科生学费计算结果!/得到研究生学费计算结果!/得到研究生学费计算结果!例2 定义三个类:物体类、球体类和长方体类、球体类和长方体类分别为物体类的子类。它们都有一个求体积的函数。#includeclass CShapepublic:CSape(double x ,double y)XCode=x ;YCode=yvirtual double Volumn() return 0.0 ;protected:double XCode , YCode ;class CBall :public CShape public:CBalldouble x,double y ,double r :CShape(x,y)Radius=r;double Volumn()return 3.14*1.33*Radius*Raius*Radius;protected:double Radius ;class CRectange :public Cshapepublic:CRectangle(double x,double y,double h) :CShape(x,y)High=h ;double Volume()return XCode*YCode*High ;protected:double High ;void Fun(CSape &p)coutp.Volumn()endl ;void main(void) CBall b1(2.0,5.0,4.0);Fun(b1);CRectangle r1(2.0,4.0,6.0);Fun(r1);运行结果:2672848 例3 虚函数与函数重载6)如果各虚函数有什么不同,系统会根据不同情况分别处理。有下面两种情况:仅返回类型不同,其余均相同,系统当出错处理。函数原型不同,仅函数名相同。此时,系统会将它认为是一般的函数重载。 此时,该函数没有能通过继承关系隐式地定义为虚函数,因此对该函数的调用不具有动态多态性。#include class CBasepublic:virtual void F1( ) cout”F1 function of CBase! n” ; virtual void F2 ( ) cout”F2 function of CBase! n” ; void F3 ( ) cout”F3 function of CBase! n” ; ;class CDerive :public CBase void F1( ) /为虚函数 cout”F1 function of CDerive ! n” ; void F2 (int x) /为重载函数 cout”F2 function of CDerive ! n” ;/ int F2( ); / A 错误,只有返回类型不同void F3 ( ) /函数覆盖 coutF1(); /调用基类版本ptr-F2(); /调用基类版本ptr-F3(); /调用基类版本ptr=&obj2 ;ptr-F1(); /动态连接,调用派生类版本ptr-F2(); /调用基类版本ptr-F3() ; /调用基类版本运行结果:F1 function of CBase !F2 function of CBase!F3 function of CBase!F1 function of CDerive !F2 function of CBase!F3 function of CBase!例4 基类构造函数调用虚函数7)在创建派生类的对象时,首先调用基类的构造函数,如果此时基类的构造函数中调用虚函数,则它应该调用虚函数的基类版本。8)构造函数不能为虚函数,但析构函数可以。#includeclass CBasepublic:CBase ( ) cout调用基类的构造函数! n” ; clone ( ) ;virtual void clone ( )cout”调用基类的clone()函数! n”:;class CDerive :public CBasepublic:CDerive ( ) cout”调用派生类中的构造函数! n” ;void clone() coutclone() ; /A 由于对象obj已经创建,故可以调用派生类版本clone()。运行结果:调用基类的构造函数!调用基类中的clone()函数!调用派生类中的构造函数!调用派生类中的clone()函数!解释: 在创建对象obj时,首先调用基类CBase的构造函数,当在该构造函数中调用clone()时,由于obj正在创建中,只做了部分初始化工作,因此尽管clone()为虚函数,此时也不能调用派生类中的版本,而只能调用基类的版本。 由于其定义的特殊性,虚构造函数是无意义的,因为虚函数只有和对象结合起来才能体现多态性。然而,虚析构函数是有意思的,而且经常使用。例5 (利用虚析构函数的一般原则是:当将基类指针或引用用new运算符指向派生类实例时,为了释放派生类实例时能调用派生类的析构函数,必须将基类的析构函数定义为虚函数。)定义两个类,其中一个类是另一个类的子类。在子类中有一个指针类型的数据成员,在构造函数中对该成员用new 进行初始化,在析构函数中将该数据成员所占用的存储空间释放。#includeclass Base public: Base( )cout”执行基类Base的构造函数。 “endl ;Base( )cout” 执行基类Base的析构函数。 “endl ; /A/virtual Base()cout” 执行基类Base的析构函数。 “endl ; /A;class Derived :public Base int *x ;public: Derived ( ) x=new int ;cout”执行派生类Derived的构造函数。”endl ;Derived ( ) delete x ; /B cout” 执行派生类Derived的析构函数。”endl ;void main() Base *p_base = new Derived ; /C 或Base &p_base=*new Derived ; delete p_base ; / 或delete &p_base ;运行结果:执行基类Base的构造函数。执行派生类Derived的构造函数。执行基类Base的析构函数。C行的指针变量p_bsse被声明为指向基类的指针。因此,每当遇到 delete p_base ;时,编译器不能判断用户要删除一个派生类实例。 将基类的析构函数声明为虚函数,即将A行改为: virtual Base ( )cout” 执行基类Base的析造函数。 “endl ; /A执行基类Base的构造函数。执行派生类Derived的构造函数。执行派生类Derived的析造函数。执行基类Base的析构函数。(8. 6. 3 纯虚函数与抽象基类) 例例6利用纯虚函数定义抽象类#include class CAbsprotected : int x ;public: CAbs( )x=1000 ; virtual void print ( ) = 0 ; void fun ( )cout”调用抽象类CAbs中的非纯虚函数”endl ;class CB:public CAbs int y ;public: CB ( )y=2000 ; void print( )cout”y=”yn; /对基类的纯虚函数重新定义;class CC:public CAbs int z ;public : CC ( )z=3000 ; void print ( )cout”z=”zprint( ) ; /错误,因为print()为纯虚函数,应去掉pa-fun( ) ; /调用抽象类中的非纯虚函数 CB b ;pa=&b ;pa-print( );CC c ;CAbs &pb=c ; /创建抽象类的引用pb.print( ) ;运行结果:调用抽象类CAbs中的非纯虚函数y=2000 z=30008.7.1 计算函数的定积分例 program 8-8.cpp p279 采用矩形法、梯形法以及simpson法来计算同一函数的定积分。 此三种方法均将区间a,b分为n等份,而后以不同方式求出各小段对应的小面积si,并将它们相加到一起来作为近似结果。#include float function(float x) /欲积分的函数return 4.0/(1+x*x); class inte_algo /基类 protected: float a,b; /a,b为积分区间的左右边界 int n; /n表示把a,b划分成多少个小区段进行积分 float h,sum; /h表示步长,sum表示积分结果值 public:inte_algo (float left,float right,int steps) a=left ; b=right; n=steps; h=(b-a)/n /算出步长 sum=0.0 ; /sum初值为0 virtual void integrate(void); /虚函数integrate; class rectangle:public inte_algo public: rectangle(float left,float right,int steps) :inte_algo (left,right,steps) virtual void integrate(void); /派生类中说明同一个虚函数integrate; class ladder:public inte_algo public: ladder (float left,float right,int steps) :inte_algo (left,right,steps) virtual void integrate(void); /派生类中说明同一个虚函数integrate;class simpson:public inte_algo public: simpson (float left,float right,int steps) :inte_algo (left,right,steps) virtual void integrate(void); /派生类中说明同一个虚函数integrate;void inte_algo:integrate() /基类虚函数定义 coutsumendl ; void rectangle:integrate() /* 派生类rectangle之虚函数integrate的类外定义,采用矩形法来计算函数的定积分。 计算公式为: sum=( f(a)+f(a+h)+f(a+2h)+.+f(a+(n-1)h) )h */float al=a; /* al为调用f函数时的实参值,依次取值 a,a+h,a+2h,. ,a+(n-1)h。 */ for(int i=0; in; i+) /共在n个点处计算函数值 sum+=function(al);al+=h; /al每次增加一个步长h;sum*=h;coutsumendl; /显示积分结果sumvoid ladder:integrate()/梯形法计算公式为: sum=( f(a)+2f(a+h)+2f(a+2h)+.+2f(a+(n-1)h)+ f(b) )h/2 */float al=a; /* al为调用f函数时的实参值,依次取值 a,a+h,a+2h,. ,a+(n-1)h。 */sum=(function(a)+function(b)/2.0); /对边界点a、b进行特殊处理 for(int i=0; in; i+) /共在n个点处计算函数值 al+=h; /al每次增加一个步长hsum+=function(al);sum*=h;coutsumendl; /显示积分结果sumvoid simpson:integrate() /simpson法 /*计算公式为: sum=( f(a)+4f(a+h)+2f(a+2h)+4f(a+3h)+2f(a+4h)+.+2f(a+(n-2)h)+ 4f(a+(n-1)h )+f(b) )h/3 */ sum=function(a)+function(b)float s=1.0 ,float al=a; /*s依次取值1、-1;1、-1; 从而使(3.0+s)依次成为公式中的系数4、2;4、2;4、2; al为调用f函数时的实参值,依次取值 a,a+h,a+2h,. ,a+(n-1)h。 */ for(int i=0; in; i+) /共在n个点处计算函数值 al+=h; /al每次增加一个步长hsum+=(3.0+s)function(al);s = -s;sum*=h/3;coutsumintegrate(); void main()rectangle rec(0.0, 1.0, 10); ladder lad(0.0, 1.0, 10); simpson sim(0.0, 1.0, 10); integrateFunc(&rec); integrateFunc(&lad);integrateFunc(&sim);/*/8.7.3 利用图元类画图的程序 /program 8-9.cpp p285#include class pixel /类pixel,表示屏幕像素点 int x,y;public:pixel() /构造函数一,无参 x=0; y=0;pixel(int a, int b) /构造函数二,参数a、b表示点的位置 x=a; y=b;pixel(const pixel& p) /构造函数三,参数p为某个已存在对象 x=p.x; y=p.y;int getx()return x; /获取对象的x值int gety()return y; /获取对象的y值; enum colort /枚举类型,用于定义颜色常量(名字)black,blue,green,cyan,red,magenta,brown,lightgray,darkgray,lightblue,lightgreen,lightcyan,lightred,lightmagenta,yellow,white,blink;class graphelem /基类graphelem(实际为抽象基类)protected:colort color; /颜色colorpublic:graphelem(colort col)color=col;virtual void draw( )=0; /纯虚函数draw ; class line:public graphelem /派生类linepixel start, end; /成员为pixel类对象 public:line(pixel sta, pixel en, colort col) :graphelem(col),start(sta),end(en) ; virtual void draw( ); /虚函数draw; class rectangle:public graphelem /派生类rectangle pixel ulcorner,lrcorner; public:rectangle(pixel ul,pixel el,colort col):graphelem(col),ulcorner(ul),lrcorner(el);virtual void draw( ); /虚函数draw;class circle:public graphelem /派生类circlepixel center; int radius; public:circle(pixel cen,int rad,colort col) :graphelem(col),center(cen)radius=rad;virtual void draw( ); /虚函数draw; class triangle:public graphelem /派生类trianglepixel pointa,pointb,pointc; public:t
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年医疗器械操作安全B级证书考试题集
- 2026年河南机电职业学院单招职业技能测试题库必考题
- 2026年庆阳职业技术学院单招职业技能考试题库及答案1套
- 2026年山西体育单招试题附答案
- 2026年医疗设备使用与维护认证题库
- 2026年工业安全之机械操作规范与事故预防试题
- 2026年智能硬件产品设计师初级模拟卷
- 2026年高校教材管理内容标准化知识点考核题
- 2026年会计从业资格考前冲刺题库与实务案例分析
- 2026年软件开发与编程基础测试题集
- 居住证明合同协议
- 2024-2025闽教版小学英语五年级上册期末考试测试卷及参考答案(共3套)
- 组件设计文档-MBOM构型管理
- 临床协调员CRC年度总结
- 编钟乐器市场洞察报告
- 负压冲洗式口腔护理
- 山东省泰安市2024-2025学年高一物理下学期期末考试试题含解析
- 净化车间液氮洗操作规程
- 《中电联标准-抽水蓄能电站钢筋混凝土衬砌水道设计导则》
- 【可行性报告】2023年硫精砂项目可行性研究分析报告
- 道路绿化养护投标方案(技术方案)
评论
0/150
提交评论