版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、第七章 继承性和派生类,7.1 基类和派生类,7.2 单继承,7.3 多继承,7.4 虚基类,7.1 基类和派生类,继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能。这样产生新的类,称派生类。派生类不是简单地继承基础类的特性,它可以调整部分成员的特性,也可以增加一些新成员。继承呈现了面向对象程序设计的层次结构。体现了由简单到复杂的认识过程。 多态性(polymorphism)也是面向对象程序设计的标志性特征。多态性是考虑在不同层次的类中,以及在同一类中,同名的成员函数之间的关系问题。函数的重载,运算符的重载
2、,属于多态性中的编译时的多态性。本章讲解的以虚基类为基础的多态性是运行时的多态性。体现了类推和比喻的思想方法。,7.1 基类和派生类,1、基类与派生类,基类(父类):已存在的用来派生新类的类;,派生类(子类):由已存在的类派生出的新类;,2、单继承与多继承,单继承:从一个基类派生的继承;,多继承:从多个基类派生的继承;,7.1 基类和派生类,(a)多重继承,(b)单继承,一个基类可以直接派生出多个派生类,派生出来的新类同样可以作为基类再继续派生出更新的类,依此类推形成一个层次结构。,7.1.1 派生类的定义,单继承的定义格式为: class 派生类名 :继承方式 基类名 派生类新定义成员 ;,
3、public:公有派生 private:私有派生 protected:保护派生,规定基类成员在派生类中的访问权限,多继承的定义格式为: class 派生类名 :继承方式1 基类名1, 继承方式2 基类名2, 派生类新定义成员 ;,单继承的定义格式:,class B /定义基类B private: int x; protected: int y; public: int z; . ;,class A:public B /由类B派生出类A private: int a; protected: int b; public: int c; . A a; /定义类A的一个对象a,7.1.1 派生类的定义
4、,不论是数据成员,还是函数成员,除构造函数与析构函数外全盘接收,声明一个和某基类成员同名的新成员派生类中的新成员就屏蔽了基类同名成员称为同名覆盖,派生类新成员必须与基类成员不同名,它的加入保证派生类在功能上有所发展。,7.1.2 派生类的三种继承方式:,公有继承(public),保护继承(private),私有继承(protected),公有继承:,公有继承其特点是: 基类的公有成员和保护成员作为派生类的成员时,都保持原有状态,而私有成员仍是私有。,公有继承:,特 别 提 示,公有继承时,派生类的对象只可访问基类中的公有成员,不能访问其它成员。派生类的成员函数可以访问基类中的公有成员和保护成员
5、,不可访问其私有成员。,公有继承:,class B private: int x; protected: int y; public: int z; .; class A:public B private: int a; protected: int b; public: int c; . A a;,说明: 类B是基类,类A是从类B公有派生的,因此类B中的public、protected属性的成员可继承到类A中来,且保持原来的属性。 因此,类A中有5个数据成员:a,b,c,y(protected属性),z(public属性)。,对象a可以直接访问public成员z和c,不能访问a,b,y。,注
6、意:,在不考虑派生类时,类中的private和protected属性的成员没有什么不同,它们都可以被类的成员函数访问,而都不能被该类的对象直接访问。 其差异主要是在派生类中,当公有继承时,基类中protected属性的成员可以作为派生类的protected属性的成员,而private属性的成员不能作为派生类的成员,class student private: int age; protected: char sex; public: int Getage( ); ; class graduatestudent: public student private: int stunum; publi
7、c: int Getnum( ); ; void graduatestudent:Getnum( )/派生类成员函数定义 /cout”age:”ageendl; /不可访问基类的私有成员 cout”stunum:”stunumendl; /派生类的私有成员 cout”age:”Getage( )endl; /基类的公有成员 cout“sex:”sexendl; /即:student:sex 基类的保护成员 ,保护继承:,其特点是:基类的所有公有成员和保护成员都作为派生类的保护成员,基类的私有成员仍是私有的。 即基类的公有成员和保护成员都作为派生类的保护成员。派生类的其他成员可以直接访问它们。派
8、生类的对象不可以直接访问它们。,.,class B private: int x; protected: int y; public: int z; .; class A:protected B private: int a; protected: int b; public: int c; . A a;,说明: 类B是基类,类A是从类B保护派生的,因此类B中的public、protected属性的成员可继承到类A中来,均变为protected属性。 因此,类A中有5个数据成员:a,b,c,y(protected属性),z(protected属性)。,对象a可以直接访问public成员c,不能
9、访问a,b,y,z。,私有继承:,基类的公有成员和保护成员都作为派生类的私有成员,并且不能被这个派生类的子类所访问。,特 别 提 示,.,class B private: int x; protected: int y; public: int z; .; class A:private B private: int a; protected: int b; public: int c; . A a;,说明: 类B是基类,类A是从类B私有派生的,因此类B中的public、protected属性的成员可继承到类A中来,均变为private属性。 因此,类A中有5个数据成员:a,b,c,y(pri
10、vate属性),z( private属性)。,对象a可以直接访问public成员c,不能访问a,b,y,z。,公有派生和私有派生的访问权限,#include class A public: void f1(); protected: int j1; private: int i1; ; class B:public A public: void f2(); protected: int j2; private: int i2; ;,class C:public B public: void f3(); ; 1、派生类B中成员函数f2()能否访问基类A中的成员:f1()、j1和i1? 2、派生类
11、B的对象b1能否访问基类A中的成员:f1()、j1和i1? 3、派生类C中的成员函数f3()能否访问直接基类B中的成员:f2()、j2和i2?能否访问间接基类A中的成员: f1()、j1和i1? 4、派生类C的对象c1能否访问直接基类B中的成员:f2()、j2和i2?能否访问间接基类A中的成员: f1()、j1和i1?,1、派生类B中成员函数f2()能否访问基类A中的成员:f1()、j1和i1?,可以访问f1()和j1,不可以访问i1; 原因:类B对类A是直接继承,可以访问A中的公有成员和保护成员,而不可以访问私有成员;,2、派生类B的对象b1能否访问基类A中的成员:f1()、j1和i1?,可
12、以访问f1(),不可以访问j1和i1; 原因:类B的对象b1对类A中的成员是水平访问,可以访问A中的公有成员,而不可以访问保护成员和私有成员;,4、派生类C的对象c1能否访问直接基类B中的成员:f2()、j2和i2?能否访问间接基类A中的成员: f1()、j1和i1?,可以访问直接基类中的f2()和j2以及间接基类中的f1() 和j1,不可以访问i2和i1; 原因:类C对类B是直接继承,原因同1;类C对类A是垂直 访问,可以访问A中的公有成员和保护成员,而不可以访 问私有成员;,可以访问直接基类中的f2()以及间接基类中的f1(),其 他都不可以访问; 原因:类C的对象c1对B中的成员是水平访
13、问,原因同2; c1对A的访问,相当于先直接继承后水平访问;,3、派生类C中的成员函数f3()能否访问直接基类B中的成员:f2()、j2和i2?能否访问间接基类A中的成员: f1()、j1和i1?,#include class A public: void f(int i) coutiendl; void g() coutgendl; ; class B:A public: void h() couthendl; A:f; ; void main() B d1; d1.f(6); d1.g(); d1.h(); ,缺省继承方式 为private,将基类中的成员 说明为派生类中 的成员,编译错。
14、B以私有继承方式继承A, 因此B的对象b1不能访问A的成员函数,输出(2): 6 h,输出(5): 6 g h,问题:,1、执行该程序时,哪个语句会出现编译错?,2、去掉出错语句后,执行结果是什么?,3、类B从类A继承时的缺省继承方式是什么?,4、派生类B中,A:f的含义是什么?,5、将B的继承方式改为public,输出结果是什么?,7.2 单继承,在单继承中,每个类可以生成多个派生类,但是每个派生类只能有一个基类。 派生类中只有一个基类是单继承的主要特点。,7.2.1 派生类构造函数和析构函数,1.派生类的构造函数,构造函数不能被继承;,派生类构造函数的工作:,对自己的数据成员进行初始化;,
15、负责调用基类构造函数使基类的数据成员得以初始化;,调用子对象的构造函数,对派生类中的子对象进行初始化;,必须在成员 初始化列表 中进行,派生类构造函数格式:,() :(), () ,成员初始化列表,成员初始化列表,B(int i,int j,int k):a(i,j)b=k;,子对象a,对子对象成员函数的调用,输出: 6,7 8,#include class A public: A(int i); void print(); const int ,A:A(int i ) a=i,r=a; /不能这样哟!,结果为:100:10:100 0:10:0,派生类构造函数的调用顺序如下:,基类的构造函数
16、 子对象类的构造函数(若有) 派生类构造函数,注意:,1、若基类中未定义构造函数,则派生类构造函数的定义中可以省略对基类构造函数的调用。 2、若基类的构造函数使用了参数,则派生类必须定义构造函数,为基类构造函数提供参数。,#include class A public: A() a=0;coutAs default constructor called.n; A(int i) a=i;coutAs constructor called.n; A() coutAs destructor called.n; void print() const couta,; int Geta()return a
17、; private:int a; class B:public A public: B() b=0;coutBs default constructor called.n; B(int i,int j,int k);,B()coutBs destructor called.n; void print(); private:int b;A aa; B:B(int i,int j,intk):A(i),aa(j) b=k; coutBs constructor called.n; void B:print() A:print(); coutb,aa.Geta()endl; void main()
18、B bb2; bb0=B(1,2,5); bb1=B(3,4,7); for(int i=0;i2;i+) bbi.print();,#include class data int x; public: data(int x)data:x=x; coutclass datan; ; class A public: A(int x):d1(x) coutclass An; private: data d1; ;,class B:public A data d2; public: B(int x) : A(x),d2(x) coutclass Bn; ; class C:public B publ
19、ic: C(int x) : B(x) coutclass Cn; ; void main( ) C object(5); ,class data class A class data class B class C,派生类析构函数:,执行派生类的析构函数时,基类的析构函数也将被调用;,析构函数不能被继承;,析构函数的执行顺序与构造函数严格相反;,派生类的析构函数;,基类的析构函数;,#include class M public: M()m1=m2=0; M(int i,int j); M(); void Print(); private: int m1,m2; M:M(int i,int
20、j) m1=i,m2=j; coutMs constructor called. m1, m2endl; M:M() coutMs destructor called. m1, m2endl; void M:Print() coutm1, m2, ;,class N:public M public: N() n=0; N(int i,int j,int k); N(); void Print(); private: int n; N:N(int i,int j,int k):M(i,j),n(k) coutNs costructor called. nendl; N:N() coutNs de
21、structor called. nendl; void N:Print() M:Print(); coutnendl; void main() N n1(5,6,7), n2(-2,-3,-4); n1.Print();n2.Print();,运行结果:,3.派生类构造函数使用中应注意的问题,派生类构造函数的定义中可以省略对基类构造函数的调用,其条件是在基类中必须有缺省的构造函数或者根本没有定义任何构造函数;,当基类的构造函数使用一个或多个参数时,派生类必须定义构造函数,提供将参数传递给基类构造函数的途径;,编译器自动生成缺省构造函数,设基类数据成员为m个,派生类数据成员为n个, 派生类的参
22、数个数为x,则:0=x=m+n;,#include class A public: A() a=0; A(int i) a=i; void Print() couta, ; private: int a; class B:public A public: B() b1=b2=0; B(int i) b1=i;b2=0; B(int i,int j,int k):A(i),b1(j),b2(k) void Print() A:Print(); coutb1, b2endl; private: int b1,b2; void main() B d1,d2(5),d3(4,5,6); d1.Prin
23、t(); d2.Print(); d3.Print();,输出: 0,0,0 0,5,0 4,5,6,7.2.2 子类型和赋值兼容规则,1、子类型 有一个特定的类型S,当且仅当它至少提供了类型T的行为,则称类型S是类型T的子类型。 子类型是类型间的一般和特殊的关系。 在继承中,公有继承可以实现子类型。 如:class A public: void print() const cout“ok!”; class B:public A public: void f() cout“No!”; ; void f1(const A 结果为:ok!,对类A的对象操作的函数,也就可对类A的子类(类B)的对象进
24、行操作,2.类型适应,指两种类型之间的关系。如:派生类适应于基类。即派生类的对象可以用于基类对象所能使用的场合。 子类型化与类型适应是一致的。 子类型的重要性是能减轻编程负担。一个函数可以用于某类型的对象,也就可用于该类型的各个子类型的对象,不必进行函数重载。,3.赋值兼容规则,赋值兼容规则是指在需要基类对象的任何地方都可以使用公有派生类的对象来替代。在替代之后,派生类对象就可以作为基类的对象使用,但只能使用从基类继承的成员。 赋值兼容规则替代的几种情况: 派生类的对象可以赋值给基类对象。 派生类的对象可以初始化基类的引用。 派生类的对象的地址可以赋给指向基类的指针。,例题1 下列对派生类的描
25、述,( )是错的。,A.一个派生类可以作另一个派生类的基类。 B.派生类至少有一个基类。 C.派生类的成员除了它自己的成员外,还包含了它的基类的成员。 D.派生类中继承的基类成员的访问权限到派生类保持不变。,答案:D,例题2 派生类的对象对它基类成员中()是可以访问的。,A.公有继承的公有成员; B.公有继承的私有成员; C.公有继承的保护成员; D.私有继承的公有成员。,答案:A,例题3 对基类和派生类的关系描述中,( )是错误。,A.派生类是基类的具体化; B.派生类是基类的子集; C.派生类是基类定义的延续; D.派生类是基类的组合。,答案:B,例题4 派生类的构造函数的成员初始化列表中
26、,不能包含( )。,A.基类的构造函数; B.派生类中子对象的初始化; C.基类的子对象的初始化; D.派生类中一般数据成员的初始化。,答案:C,7.3 多继承,在册人员,学生(单继承),教职工(单继承),兼职教师(单继承),教师 (单继承),行政人员 (单继承),工人 (单继承),研究生 (单继承),行政人员兼教师 (多重继承),在职研究生 (多重继承),研究生助教 (多重继承),7.3 多继承,多继承的定义格式为: class 派生类名 :继承方式1 基类名1, 继承方式2 基类名2, 派生类新定义成员 ;,由多个基类共同派生出新的派生类,这样的继承结构被称为多重继承或多继承(multip
27、le-inheritance),多重继承的定义格式:,如: class A ; class B ; class C :public A,public B ; 根据继承的规定,派生类C的成员包含了基类A中成员和基类B中成员及该类本身的成员。,#include class A public: void printA()coutHello ; ; class B public: void printB()coutC+ ; ; class C: public A,public B public: void printC()coutWorld!n; ; void main() C obj; obj.pr
28、intA(); obj.printB(); obj.printC(); ,Hello C+ World!,7.3.2 多继承的构造函数和析构函数,() :(), () (), . 它必须同时负责该派生类所有基类构造函数的调用。同时,派生类的参数个数必须包含完成所有基类初始化所需的参数个数。,多继承的构造函数:,派生类构造函数的调用顺序是: 先执行所有基类的构造函数 再执行子对象类的构造函数(若有) 再执行派生类本身的构造函数 注意: 同一层次的各基类构造函数的执行顺序取决于定义派生类时所指定的各基类顺序,与派生类构造函数中所定义的成员初始化表的各项顺序无关。,定义基类B1,定义 基类B2,定义
29、基类B3,派生类构造函数,定义派生类A,定义子对象bb,调用不同基类中的同名函数,运行结果:,多继承的析构函数:,在多继承中,析构函数的执行顺序与构造函数的顺序正好相反。,#include class A public: A()coutA Constructorendl; A()coutA Destructorendl; ; class B public: B()coutB Constructorendl; B()coutB Destructorendl; ; class C:public A,public B public: C()coutC Constructorendl; C()cout
30、C Destructorendl; ; void main() C c;,A Constructor B Constructor C Constructor C Destructor B Destructor A Destructor,7.3.3 多继承的二义性问题,1、产生二义性的原因,在多继承情况下,造成的对基类中某个成员的访问出现的不唯一的情况;,二义性问题,class A class C:public A,public B public: public: void f(); void g(); ; void h(); class B ; public: void f(); void g
31、(); ;,二义性问题,问题:若定义C c1;,则c1.f()是否正确?,答:c1.f()将产生二义性;,原因:不能识别是调用类A或类B的f函数;,解决方法: a.区别出是类A或类B的f函数; c1.A:f();或c1.B:f(); b.在类中定义同名函数f;,二义性问题,当一个派生类从多个基类派生,而这些基 类又有一个共同的基类,则对该基类中说明的成员进行访问时,可能会出现二义性;,二义性问题,class Aclass B2:public A public: private: int a; int b2; ; ; class B1:public Aclass C:public B1,publ
32、ic B2 private: public: int b1; int f(); ; private: int c;,二义性问题,问题:若定义C c1;,则c1.a与c1.A:a是否正确?,答:c1.a与c1.A:a将产生二义性;,原因:不能识别是通过类B1或类B2调用类A的a;,解决方法: a.区别出是通过类B1或类B2调用类A的a; c1.B1:a;或c1.B2:a; b.虚基类;,2、二义性解决方法,利用成员名限定法消除二义性;,在类中定义一个同名成员;,虚基类;,3、支配规则(定义同名成员方法),支配规则:类X中的名字N支配类Y中同名的名字N是指类X以类Y为它的一个基类;,如果一个名字支
33、配另外一个名字,则二者之间不存在二义性。当选择该名字时,使用支配者的名字;,4、说明,一个类不能从同一个类中直接继承一次以上;,二义性检查在访问控制和类型检查之前进行,访问控制和类型检查不能解决二义性问题;,运行结果:,7.4 虚基类,引入目的:解决二义性问题;,格式:,virtual ,说明: 关键字virtual与关键字public或private的相对位置无关,但必须位于虚基类名之前,且virtual只对紧随其后的基类名起作用;,7.4 虚基类,例如: class D:virtual public A,private B,virutal public C 其中:类A和类C是虚基类,而类B
34、是非虚基类,class A public: void f(); protected: int a; class B:virtual public A protected: int b; class C:virtual public A protected: int c; class D:public B,public C public: int g(); private: int d;,虚基类,虚基类,下列各语句是否正确? D n; n.f(); void D:g() f();,正确 能够唯一确定调用 类A的f();,7.4 虚基类,虚基类的初始化,由于派生类的对象中只有一个虚基类子对象。为保
35、证虚基类子对象只被初始化一次,这个虚基类构造函数必须只被调用一次。,虚基类的初始化,C+规定: 虚基类子对象是由最派生类的构造函数通过调用虚基类的构造函数进行初始化的。 虚基类的构造函数在非虚基类之前调用; 若同一层次中包含多个虚基类,这些虚基类的构造函数按它们说明的次序调用; 若虚基类由非虚基类派生而来,则仍先调用基类构造函数,再调用派生类的构造函数。,最派生类:,若定义E e;则E是最派生类; 若定义D d;则D是最派生类; 若定义B b;则B是最派生类; 若定义C c;则C是最派生类;,#include class base1 public: base1()coutclass base1
36、endl; ; class base2 public: base2()coutclass base2endl; ; class level1:public base2,virtual public base1 public: level1()coutclass level1endl; ; class level2:public base2,virtual public base1 public: level2()coutclass level2endl; ; class toplevel:public level1,virtual public level2 public: toplevel(
37、)coutclass toplevel1endl; ; void main() toplevel obj;,运行结果:,说明:,虚基类子对象由最派生类构造函数进行初始化;,虚基类子对象只被初始化一次;,虚基类构造函数先于非虚基类构造函数执行;,设置虚基类的目的是:,A 简化程序;,B 消除二义性;,C 提高运行效率,D 减少目标代码,答案:B,带有虚基类的多层派生类构造函数的成员初始化列表中都要列出虚基类的构造函数,这样将对虚基类的子对象初始化(),A 与虚基类下面的派生类个数有关,B 多次,C 二次,D 一次,答案:D,#include class A public: A(int i,int
38、 j) a=i;b=j; void Move(int x,int y) a+=x;b+=y; void Show() cout(a,b)endl; private: int a,b; class B:public A public: B(int i,int j,int k,int l):A(i,j),x(k),y(l) void Show() coutx,yendl;,void fun() Move(3,5); void f1() A:Show(); private: int x,y; void main() A e(1,2); e.Show(); B d(3,4,5,6); d.fun();
39、 d.A:Show(); d.B:Show(); d.f1(); ,运行结果:,#include class P public: P(int p1,int p2) pri1=p1;pri2=p2; int inc1() return +pri1; int inc2() return +pri2; void display() coutpri1=pri1,pri2=pri2endl; private: int pri1,pri2; class D1:virtual private P public: D1(int p1,int p2,int p3):P(p1,p2) pri3=p3; int i
40、nc1() return P:inc1(); int inc3() return +pri3; void display() P:display(); coutpri3=pri3endl; private: int pri3;,class D2:virtual public P public: D2(int p1,int p2,int p4):P(p1,p2) pri4=p4; int inc1() P:inc1(); P:inc2(); return P:inc1(); int inc4() return +pri4; void display() P:display(); coutpri4
41、=pri4endl; private: int pri4;,class D12:private D1,public D2 public: D12(int p11,int p12,int p13,int p21,int p22,int p23,int p) :D1(p11,p12,p13),D2(p21,p22,p23),P(p11,p21) pri12=p; int inc1() D2:inc1(); return D2:inc1(); int inc5() return +pri12; void display() coutD2:display()n; D2:display(); coutp
42、ri12=pri12endl; private: int pri12;,void main() D12 d(1,2,3,4,5,6,7); d.display(); coutendl; d.inc4(); d.inc5(); d.D12:inc1(); d.display(); ,运行结果:,8.7 多态性与虚函数,C+的三大特征:,封装性,继承性,多态性,多态性是指同一个消息被不同类型的对象接收时产生不同的行为,特点就是一个接口,多个实现。+中多态性按照类型可以分为强制多态、过载多态、包含多态和参数多态四种。,8.7 多态性与虚函数,8.7 多态性与虚函数,强制多态是指通过语义操作,强制数据
43、做本不属于该类型数据的操作。编译器内部的数据的隐式转换,比如3.0+4操作时转换成3.0+4.0就属于此种类型 重载多态是指函数重载,同名的操作在不同的环境下有不同的行为。前面学习过的普通函数重载和将要学习的类成员函数重载、运算符重载都属于此种类型。 包含多态是指在同一类族中定义于不同类中的同名函数的多态行为。我们本章将要学习的虚函数就属于此种类型。 参数多态是指功能、结构实现相同但所作用于的数据类型不同,也就是数据类型参数化的多态。函数模板和类模板就属于此种多态。,多态的实现:,多态是指同一个消息被不同的对象接收产生不同的行为,因此,多态在实现的时候必须确定消息的操作对象。我们根据消息和对象
44、相结合的时间分为两种: 在程序编译连接阶段完成的,也就是说在编译的过程中确定了消息的操作对象,我们称为静态联编(静态束定)。 在程序运行阶段完成的,也就是说在程序运行的过程中才确定消息的操作对象,我们称为动态联编(动态束定)。,多态的实现:,#include class Point public: Point(double i, double j) x=i; y=j; double Area() const return 0.0; private: double x, y; ; class Rectangle:public Point public: Rectangle(double i, d
45、ouble j, double k, double l); double Area() const return w*h; private: double w,h; ; Rectangle:Rectangle(double i, double j, double k, double l) :Point(i,j) w=k; h=l; void fun(Point ,Area=0,动态联编:,动态联编:在程序执行时进行的束定;,实现:C+动态束定在虚函数的支持下实现;,动态联编的原因:,当实现一个子类型时变动了其基类中相应行为的实现时,必须将这种变动告诉编译器,即进行动态联编;,8.7.1虚函数的
46、定义,1、虚函数,虚函数是动态联编的基础;,虚函数是非static成员函数;,virtual (),说明方法:,1、虚函数,含义:,若类中一成员函数被说明为虚函数,则该成员函数在派生类中可能有不同的实现。当使用该成员函数操作指针或引用所标识的对象时,对该成员函数调用可采用动态联编方式。,操作方法:,动态联编只能通过指针或引用标识对象来操作虚函数。如果采用一般类型的标识对象来操作虚函数,则将采用静态联编方式调用虚函数。,#include class Point public: Point(double i,double j) x=i;y=j; virtual double Area() cons
47、t return 0; private: double x,y; class Rectangle:public Point public: Rectangle(int i,int j,int k,int l); virtual double Area() const return w*h; private: double w,h; Rectangle:Rectangle(int i,int j,int k,int l):Point(i,j) w=k; h=l; void fun(Point ,虚函数,虚函数,输出: 375,#include class Point public: Point(
48、double i,double j) x=i;y=j; virtual double Area() const return 0; private: double x,y; class Rectangle:public Point public: Rectangle(int i,int j,int k,int l); virtual double Area() const return w*h; private: double w,h; Rectangle:Rectangle(int i,int j,int k,int l):Point(i,j) w=k; h=l; void fun(Poin
49、t *s) coutArea()endl; void main() Rectangle rect(3.0,5.2,15.0,25.0); fun(,输出: 375,#include class Point public: Point(double i,double j) x=i;y=j; virtual double Area() const return 0; private: double x,y; class Rectangle:public Point public: Rectangle(int i,int j,int k,int l); virtual double Area() c
50、onst return w*h; private: double w,h; Rectangle:Rectangle(int i,int j,int k,int l):Point(i,j) w=k; h=l; void fun(Point s) couts.Area()endl; void main() Rectangle rect(3.0,5.2,15.0,25.0); fun(rect);,输出: 0,说明:,1.派生类中定义虚函数必须与基类中的虚函数同名 外,还必须同参数表,同返回类型。否则被认为是 重载,而不是虚函数。如基类中返回基类指针,派 生类中返回派生类指针是允许的,这是一个例外。 2.只有类的成员函数才能说明为虚函数。这是因为虚 函数仅适用于有继承关系的类对象。 3.静态成员
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026东国大学面试题目及答案
- 环保行业智能化环境监测与污染治理方案
- 绿色能源技术发展趋势研究手册
- 关于2026年品牌合作活动执行细节的确认函(3篇范文)
- 2026公司开发岗面试题及答案
- 2026沟通艺术面试题及答案
- 关于逾期货款支付的催缴通知函8篇范文
- 科学预防传染护航健康成长,小学主题班会课件
- 2026核算测试面试题及答案大全
- 2025-2026学年福州市高考仿真卷生物试卷含解析
- 搅拌站安全会议管理制度
- T/CI 307-2024用于疾病治疗的间充质干细胞质量要求
- 2024小学科学教师教学技能测试题及答案
- 混凝土站生产流程
- 通站(2017)8012 铁路站场排水构筑物
- 《工业网络技术与应用(微课版)》 课件 第4章 网络冗余技术
- 云南省公路工程试验检测费用指导价
- 个人入股合同协议书
- 马克思主义与社会科学方法论课后思考题答案全
- 华信惠悦咨询美的集团职位分析与职位说明书研讨会
- 加油站向周边商户风险告知书
评论
0/150
提交评论