1 / 53

第六章 类和对象

第六章 类和对象. 6 .1 面向对象程序设计概述 6 .2 结构 6.3 类和对象 6.4 继承和派生 6.5 多态性 6.6 程序举例. 6.1 面向对象程序设计( OOP )概述. Object Oriented Programming. 基本概念. 对象:现实世界的实体,每个对象都有所属的类 类: 对一组对象共同具有的属性和行为的抽象, 具有封装和隐藏性、还具有继承性。 消息:向某对象请求服务的一种表达方式,是对 象与外界、对象与其它对象之间联系的工具 方法:对某对象接受消息后所采取的操作的描述。.

dextra
Download Presentation

第六章 类和对象

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第六章 类和对象 6.1 面向对象程序设计概述 6.2 结构 6.3 类和对象 6.4 继承和派生 6.5多态性 6.6 程序举例

  2. 6.1 面向对象程序设计(OOP)概述 Object Oriented Programming • 基本概念 • 对象:现实世界的实体,每个对象都有所属的类 • 类: 对一组对象共同具有的属性和行为的抽象, 具有封装和隐藏性、还具有继承性。 • 消息:向某对象请求服务的一种表达方式,是对 象与外界、对象与其它对象之间联系的工具 • 方法:对某对象接受消息后所采取的操作的描述。

  3. 特点 封装性 继承性 多态性 C++中,通过类和对象实现对数据的封装,使得程序的修改维护更方便。是OOP的基础。 连接类与类的层次模型,利用现有类派生出新类的过程称为类继承,支持代码重用、提供了无限重复利用程序资源的途径、节省程序开发的时间和资源,是OOP的关键。 发出同样的消息被不同类型的对象接收时导致完全不同的行为,是OOP的重要补充

  4. 6.2 结构 C++中的类从C语言中的结构概念演变而来 结构类型说明形式 struct结构类型标识符 { 结构成员1; 结构成员2; ┆ 结构成员n; }; 说明结 构类型 的关键字 类型可任意 (不能为该结构自身)

  5. 如,说明一个结构类型date,含三个整型数据成员如,说明一个结构类型date,含三个整型数据成员 struct man { char name[15]; char sex; int age; date birthday; }; struct date { int month; int day; int year; }; 在此基础上,又可说明另一个结构类型man birthday Name sex age month day year struct man 结构类型

  6. 结构变量定义 struct man man1, man2; • 先说明结构类型再定义结构变量 • 在说明结构数据类型的同时定义结构变量 • 省略结构标识符直接定义结构类型变量 struct { char name[15]; char sex; int age; struct date birthday; } man1, man2; struct man { char name[15]; char sex; int age; struct date birthday; } man1, man2; 无类型名变量

  7. 结构变量的引用 成员访问运算符 优先级最高的 四个运算符之一 形式: 结构变量名.成员名 (*指向结构的指针).成员名 指向结构的指针->成员名 或 或 括号不能少 通过指向结构的指针引用结构变量成员 如,假设有定义 man m,*p=&m; 则可如下引用结构成员 strcpy (m.name, "Fang Min"); p->birthday.month = 8;

  8. 6.3 类和对象 引例 #include "iostream.h" class Circle {private: double x,y,r; public: void print() {cout<<"圆心:("<<x<<","<<y<<")"<<endl; cout<<"半径:"<<r<<endl; } void set(double x1,double y1,double r1) { x=x1; y=y1; r=r1;} }; 类定义 void main() { Circle p; p.set(0,0,2); p.print(); } 定义类对象 数据成员 成员函数 对对象调用 成员函数 Circle类将圆的属性(圆心坐标和半径)和操作(print、set)封装在一起

  9. 数据成员 成员函数 名称 含义 名称 功能 x 圆心坐标x值 set 设置数据成员值 y 圆心坐标 y值 print 输出数据成员值 r 圆半径 上述定义的Circle类实际上也相当于一种新的数据类型,包含了数据和对数据的操作,其成员描述如下:

  10. 6.3.1 类的定义 类是一种复杂的数据类型,它是将不同类型的数据和与这些数据相关的运算封装在一起的集合体,类的结构是用来确定一类对象的行为,而这些行为是通过类的内部数据结构和相关的操作来确定的。 定义格式: 定义类的关键字 说明部分 class 类名 {public: <成员函数或数据成员的说明>; private: <成员函数或数据成员的说明>; protected: <成员函数或数据成员的说明>; }; <各成员函数的实现> 访问权限修饰符 类的说明 类的说明 类的说明 类的说明 实现部分 实现部分

  11. 说明: • 定义包括说明部分和实现部分。若成员函数在说明部分已定义,则实现部分可省略。 • 访问权限修饰符:public(公有)、private(私有 )和 protected(保护) 缺省时为private。 • 公有成员通常为成员函数,可在程序中引用,私有成员通常是数据成员,只有成员函数或友元函数才可引用。 • 类体中不允许对数据成员初始化。 • 自身类的对象不可以作为自己的成员 class B {private: int year=2002, month=10, day=12; B b; …… }; 错

  12. 数据成员 成员函数 名称 含义 名称 功能 name 职员姓名 set 设置数据成员值 sex 职员性别 display 输出数据成员值 wage 职员工资 如,定义一个职工类,该类是对所有职工某些信息的抽象,包括如下成员: 作用域运算符(类体外实现时需要) class Staff {private: char name[30]; char sex; float wage; public: void display(); void set(char *n,char s,float w); }; void Staff::display() {cout<<name<<":"<<sex<<","<< wage<<endl; } void Staff::set(char *n,char s,float w) { strcpy(name,n); sex=s; wage=w; } 说明部分 实现部分

  13. 6.3.2 对象的定义 类名仅提供一种类型定义,只有在定义属于类的变量后,系统才会为其预留空间,这种变量称为对象,它是类的实例。 格式: 如,假设A是一个已定义过的类,则可定义: 类名 对象名表; A a1,*p,a[5] A类的对象 对象数组 指向A类对象的指针

  14. 引用方式同结构成员 • 成员引用 • 一般对象成员 • 数据成员: • 成员函数: • <对象名> . <成员名>(<参数表>) • 指向对象的指针的成员表示法: • 数据成员: • 成员函数: 对象名 .成员名 对象名.成员名(参数表) 对象指针名->成员名 (*对象指针名).成员名 或 对象指针名->成员名(参数表) (*对象指针名.成员名(参数表)

  15. [例6-1] 可修改为如下形式吗? #include "iostream.h" #include "string.h" class Staff {private: char name[30]; char sex; float wage; public: void display() {cout<<name<<":"<<sex<<", "<<wage<<endl;} void set(char *n,char s,float w) {strcpy(name,n); sex=s; wage=w; } }; s.name= “WangQiang” s.sex=‘m’; s.wage=1526 void main() {Staff s,*s1; s.set(“WangQiang”,‘m’,1526); s.display(); s1=&s; s1->set("GaoLing",'f',2003); s1->display(); } S1为指向s的指针

  16. 6.3.3 对象的初始化 1.构造函数和析构函数 [例6-2] 看引例的另一种实现 1.定义的同时初始化对象 2.省略对赋初值成员函数的额外调用 #include "iostream.h" class Circle {private: double x,y,r; public: void print() {cout<<"圆心:("<<x<<","<<y<<")"<<endl; cout<<"半径:"<<r<<endl; } Circle(double x1,double y1,double r1) { x=x1; y=y1; r=r1;} }; void main() { Circle p (0,0,2); p.print(); } 构造函数、同类名

  17. 构造函数特点 析构函数特点: • 是成员函数,可写在类体内,亦可写在类体外。 • 函数名同类名,不能指定函数类型,可以带参数。 • 可重载,即可定义多个参数个数不同的函数。 • 在创建对象时由系统自动调用,程序中不能直接调用。 • 是成员函数,可写在类体内,亦可写在类体外。 • 函数名同类名,前面多个字符“~” ,不指定类型,无参。 • 不可重载,即一个类只能定义一个析构函数。 • 可被调用,也可由系统调用。系统自动调用情况如下: • 若一个对象被定义在函数体内,则当该函数结束时, 该对象的析构函数被自动调用。 • 当一个对象是使用new运算符被动态创建的,在使用delete释放时,析构函数将会被自动调用

  18. 2.缺省构造函数和缺省析构函数 • 形式: • 说明: • 若没有定义任何构造函数,系统会自动生成上述无参的缺省构造函数及析构函数 • 若定义一个静态对象而没有指明初始化时,编译器会按缺省构造函数对对象的所有数据成员都初始化为0或空。 <类名>::<缺省构造函数名>( ) { } <类名>::~<缺省析构函数名>() { }

  19. [例6.3] 定义一个Circle1类,具有求一个圆的面积、求两个圆的面积之和,以及输出面积等功能 。 #include "iostream.h" class Circle1 {private: double x,y,r,s; public: void print() {cout<<"圆心:("<<x<<","<<y<<")"<<endl; cout<<"半径:"<<r<<endl; } Circle1() { } Circle1(double x1,double y1,double r1) { x=x1; y=y1; r=r1;} void addarea(Circle1 p1,Circle1 p2) {s=3.14*(p1.r*p1.r)+3.14*(p2.r*p2.r);} void disp() { cout<<"面积:"<<s<<endl;} }; void main() { Circle1 p1(0,0,2),p2(1,1,4),p3; p1.print(); p2.print(); p3.addarea(p1,p2); p3.disp(); } 初始化了吗 可缺省吗?验证一下

  20. [例6.4] 析构函数示例 析构函数中输出处理结果(未设专门输出函数) #include <iostream.h> #include <conio.h> class count {int num; public: count(); ~count(); void process(); }; count::count() {num=0;} count::~count() {cout<<"字符个数:"<<num<<endl;} void count::process() {while(cin.get()!='\n') num++; cout<<endl; } void main() {count c; cout<<"输入一个句子:" ; c.process(); } 析构函数在程序结束 前由系统自动调用

  21. 3.拷贝初始化构造函数 [例6.5] • 用于用已知对象初始化被创建的同类对象 • 只有一个参数,且是对某个对象的引用 • 常用于做函数的形参及返回值 拷贝初始化构造函数(引用做参数) #include "iostream.h" class Circle1 { private: double x,y,r,s; public: void print() {cout<<"圆心:("<<x<<","<<y<<")"<<endl; cout<<"半径:"<<r<<endl; } Circle1(double x1,double y1,double r1) { x=x1; y=y1; r=r1;} Circle1( Circle1 &p) {x=p.x; y=p.y, r=p.r;} }; void main() {Circle1 p1(0,0,2),p2(p1); p1.print(); p2.print(); } 已知对象做初值

  22. 6.3.4常对象和常成员 1.常成员函数 形式: 类型说明符 函数名(参数表) const 说明: • 不修改对象数据成员的成员函数才能声明为const函数 • 构造函数和析构函数不能声明为const • 只有常成员函数可以操作常对象 [例6.6]常成员函数示例

  23. #include "iostream.h" class Time {private: int hour,minute,second; public: Time::Time() { } Time::Time(int h,int m,int s) {hour=h; minute=m; second=s;} void settime(int h,int m,int s) {hour=h; minute=m; second=s;} void print()const {cout<<hour<<":"<<minute<<":"<<second<<endl;} }; void main() {Time t1; const Time t2(10,23,34);//定义t2为常对象 t1.settime(11,15,20); t1.print(); //t2.settime(4,12,15); t2.print(); } settime函数可声明为const吗 不修改数据成员,定义为常函数 前面的解释符可去掉吗

  24. 2.常数据成员 对不应该被修改的数据成员声明为const,可使其受到强制保护,初始化方式与一般数据成员不同。 class Decrement { private: int num; const int dec; //将dec声明为常数据成员 public: Decrement(int n,int d):dec(d) { num=n;} void fdec() {num=num-dec; } void print()const {cout<<"num="<<num<<",dec="<<dec<<endl; } }; 初始化列表的方式初始化

  25. 6.3.5静态成员 静态成员的提出是为了解决数据共享的问题,它比全局变量在实现数据共享时更为安全,是实现同类多个对象数据共享的好方法。在类中,分为静态数据成员和静态函数。 1。静态数据成员 初始化格式: • 是类的成员,被所有对象所共享,在内存中只存贮一次 • 定义或说明时前面加关键字static • 初始化在类外进行,不加static和访问权限修饰符 数据类型 类名::静态数据成员=值

  26. [例6.7] 静态数据成员示例程序 通过以下程序了解静态数据成员的声明、初始化的位置和限定及具有类对象共享的属性。 创建A时 k值0->1 创建B时 k值1->2。 静态变量声明 静态变量初始化 void main() { Tc A,B; A.display(); B.display(); } 运行结果: #include <iostream.h> class Tc {private: int i; static int k; public: Tc( ) {i=0; i++; k++;} void display() { cout<<i<<","<<k; } }; int Tc::k=0; 1,2 1,2

  27. 2.静态成员函数 调用形式: 静态成员函数中数据成员的引用也有区别: [例6.8]静态成员函数应用程序示例 静态成员函数是类的成员函数,而非对象的成员。 类名::静态成员函数名(参数表) • 对静态数据成员,直接引用 • 对非静态数据成员,通过对象引用

  28. #include <iostream.h> class Tc {private: int A; static int B; public: Tc(int a) {A=a; B+=a;} static void display(Tc C) { cout<<C.A<<B; } }; int Tc::B=2; void main() { Tc A(2),B(4); Tc::display(A); Tc::display(B); } 静态成员函数的调用 静态数据成员的引用 非静态数据成员的引用 通过该程序了解程序中静态成员函数的调用方式以及静态成员函数中静态数据成员和非静态数据成员的引用方式

  29. 前不能加 friend 6.3.6 友元函数 [例6.9]友元函数示例程序 • 为非成员函数 • 可访问类中私有成员 • 说明时前面加关键字friend标识 void Cpoint::print() { cout<<X<<Y ; } double dist(Cpoint &a,Cpoint &b) { int dx=a.X-b.X; int dy=a.Y-b.Y; return sqrt(dx*dx+dy*dy); } void main() {Cpoint p1(3,4),p2(6,8); p1.print(); p2.print(); double d=dist(p1,p2); /*友元不是成员函数不需对象表示,直接调用*/ cout<<"Distance is "<<d<<endl; } #include <iostream.h> #include <math.h> class Cpoint {private: int X,Y; public: Cpoint(int x, int y) { X=x; Y=y; } void print(); friend double dist(Cpoint &a,Cpoint &b); }; 友元函数说明

  30. 计算机系人员 教职工 学生 教师 行政管理人员 教务 本科生 研究生 系主任 6.4 继承和派生 基类(父类) 单继承 派生类 (子类) 多继承

  31. 从Circle类中派生而来 对比如下两个圆柱体类的定义 class Cylinder {private: double x,y,r,h; public: void print() { cout<<"圆心:("<<x<<", " <<y<<")"<<endl; cout<<"半径:"<<r <<",圆柱高:"<<h<<endl; } void set(double x1,double y1, double r1,double h1) { x=x1; y=y1; r=r1; h=h1;} }; 全部数据成员重新定义 class Cylinder1:public Circle {private: double h; public: void print() {Circle::print(); cout<<"圆柱高:"<<h<<endl; } void set(double x1,double y1, double r1,double h1) { Circle::set(x1,y1,r1); h=h1; } }; 只定义一个新成员(Circle中没有) 通过调用Circle类成员函数输出Circle类成员

  32. 6.4.2单继承 1.派生类的定义格式 public(公有基类) private(私有基类) protected(保护基类) class 派生类名: 继承方式 基类名 { 派生类新定义成员}; 若要在派生类Cylinder1中再增加一个成员函数volume,用以求圆柱体的体积,则该成员函数能否如下实现: 原有类(父类) 错! double Cylinder1::volume() {return(3.14*r*r*h);} r是Circle类的私有成员, 不能被派生类访问

  33. 2.继承方式 public,private和 protected 是三种常用的继承方式,继承方式的不同决定了派生类对基类成员的访问权限不同。 派生类的继承关系

  34. [例6.10]分析下列程序中的访问权限,并回答所提的问题。[例6.10]分析下列程序中的访问权限,并回答所提的问题。 #include <iostream.h> class A {public: void f1(); A( ) {i1=10;j1=11;} protected: int j1; private: int i1; }; class B:public A {public: void f2( ); B( ) {i2=20;j2=21;} protected: int j2; private: int i2; }; class C:public B {public: void f3(); C( ) {i3=30;j3=31;} protected: int j3; private: int i3; }; void main() {A a; B b; C c; } (1) f2()能否访问f1(),i1,j1? 能访问f1()、j1,不能访问i1 (2) b能否访问f1(),i1,j1? 能访问f1(),不能访问i1和j1 (3) f3()能否访问f2()、i2和j2,以及f1(),j1和i1? f3能访问f2()和j2,以及f1()和j1,但不能访问i1和i2 (4)c能否访问f2(),i2和j2?以及f1(),j1和i1? 能访问f2()和f1(),其它的都不能访问

  35. [例6.11]派生类示例程序 #include "iostream.h" class Circle {private: double x,y,r; public: void print() {cout<<"圆心:("<<x<<","<<y<<")"; cout<<endl<<"半径:"<<r<<endl; } void set(double x1,double y1,double r1) { x=x1; y=y1; r=r1; } double getr() {return r;} }; class Cylinder1:public Circle {private: double h; public: void print() {Circle::print(); cout<<"圆柱高:"<<h<<endl; } void set(double x1,double y1, double r1,double h1) { Circle::set(x1,y1,r1); h=h1;} double volume() {double R=getr(); return(3.14*R*R*h); } }; void main() {Cylinder1 p; p.set(0,0,2,3); p.print(); cout<<"volume="<<p.volume(); } 派生类可访问基类公有成员 该函数返回值为圆半径,为派生类能使用半径提供一个接口

  36. 3.构造函数和析构函数 派生类的构造函数除了对自己的数据成员初始化外,还负责调用基类构造函数使基类的数据成员得以初始化,当对象被删除时,派生类的析构函数被执行,同时基类的析构函数也将被调用。 格式: 派生类名(派生类构造函数总参数表):基类构造函数(参数表1) {<派生类中数据成员初始化>}; 说明: • 基类中有缺省的构造函数或没定义构造函数,则派生类构造函数的定义中可省略对基类构造函数的调用,而隐式调用缺省构造函数。 • 基类构造函数中,只有有参的构造函数,则派生类构造函数中必须 调用基类构造函数,提供将参数传递给基类构造函数的途径 • 派生类构造函数的调用顺序为先基类,后派生类。 • 派生类析构函数的执行顺序为先派生类,后基类。

  37. [例6.12]派生类构造函数示例程序 class Staff1:public Staff {private: int wt; public: Staff1(char *n,char s,float w,int t):Staff(n,s,w) {wt=t;} double addwage() {return(wt/10*80);} void display() { Staff::display(); cout<<wt<<", " <<addwage()<<endl; } }; void main() {Staff1s("WangQiang",'m',1526,21); s.display(); } #include"iostream.h" #include "string.h" class Staff {private: char name[30]; char sex; float wage; public: void display() {cout<<name<<":"<<sex<<", " <<age<<endl; } Staff(char *n,char s,float w) { strcpy(name,n); sex=s; wage=w; } }; 派生类构造函数中调用基类构造函数

  38. 6.5多态性 发出同样的消息被不同类型的对象接收时导致完全不同的行为。 • 函数重载(已介绍过) • 运算符重载 • 基于虚函数的多态性 6.5.1 运算符重载 赋予已有的运算符多重含义,通过重新定义运算符使它能够用于特定类的对象以完成特定的功能。 [例6.13]重载“+”运算 ,用以实现两个字符串的连接

  39. #include "iostream.h" #include "string.h" #include "stdio.h" class Str {private: char *s; int len; public: Str() { } Str(char *s1) { len=strlen(s1); s=new char[len]; strcpy(s,s1); } void print() {cout<<s<<endl; } Str operator+(Str s1) { return(strcat(s,s1.s)); } }; void main() { char str1[100],str2[100]; gets(str1); gets(str2); Str s1(str1),s2(str2),s3; s3=s1+s2; s3.print(); } s3=s1.operator+(s2) 对加法运算符进行重载

  40. 重载形式: 重载为类的成员函数: 类名 operator 运算符(参数表) 程序中表达形式: c1 运算符 c2 编译程序解释形式: c1 operator 运算符(c2) 重载为类的友元函数: friend类名operator运算符(参数表) 程序中表达形式: c1 运算符 c2 编译程序解释形式: operator 运算符(c1,c2) 隐含了指向c1的this指针 将例6.13中的加法运算符重载为友元函数的形式如下: friend Str operator+(Str s1,Str s2) {return(strcat(s1.s,s2.s));}

  41. this指针 • 无需定义而隐含于每个类的成员函数中 • 指向正在被某个成员函数操作的对象 • 可以用*this来标识调用该成员函数的对象 • 通常情况下,程序中并不显式地使用this指针 [例6.14]自增运算符重载(this指针使用示例)

  42. #include "iostream.h" class A {private: int x; public: A(int x1) {x=x1; } void print() {cout<<x<<endl;} A operator++() {x++; return(*this); } }; void main() {A a(5); (++a).print(); } 返回调用成员函数的对象自身 等价于如下两条语句: ++a; a.print(); 自增重载运算作用于A类对象a

  43. 6.5.3虚函数 虚函数说明方式 虚函数是动态联编的基础,它是一种非static的成员函数 实现动态联编的条件 virtual类型说明符 函数名 (参数表) • 基类中有说明的虚函数 • 调用虚函数操作的只能是对象指针或对象引用,否则仍为静态联编 [例6.15]虚函数示例程序

  44. #include "iostream.h" class Animal {public: void character() {cout<<"动物特征:不同.\n";} virtual food() {cout<<"动物食物:不同.\n";} }; class Giraffe:public Animal {public: void character() {cout<<"长颈鹿特征:长颈.\n";} virtual food() {cout<<"长颈鹿食物:树叶.\n";} }; class Elephant:public Animal {public: void character() {cout<<"大象特征:长鼻子.\n";} virtual food() {cout<<"大象食物:草.\n";} }; void f(Animal *p)//形参数基类指针 {p->character(); p->food(); } void main() {Giraffe g; f(&g); //实参为派生类对象的地址 Elephant e; f(&e); //实参为派生类对象的地址 } 观察运行结果

  45. 若将程序的相应部分修改为如下两种形式,再观察运行结果若将程序的相应部分修改为如下两种形式,再观察运行结果 void f(Animal &p)//形参为基类 对象的引用 {p.character(); p.food(); } void main() {Giraffe g; f(g);//实参为派生类对象 Elephant e; f(e); //实参为派生类对象 } void f(Animal p)//形参为基类 对象 {p.character(); p.food(); } void main() {Giraffe g; f(g);//实参为派生类对象 Elephant e; f(e); //实参为派生类对象 }

  46. 从上述程序中可见: 只有当虚函数操作的是指向对象的指针或是对象的引用时,对该虚函数调用采取的才是动态联编。 虚函数使用说明: • 派生类中的虚函数应与基类中的虚函数具有相同的名称、参数个数及参数类型。 • 可以只将基类中的成员函数显式地说明为虚函数,而派生类中的同名函数也隐含为虚函数。

  47. 6.5.4 抽象类 1.纯虚函数 是一种没有函数体特殊的虚函数,当在基类中不能对虚函数给出有意义的实现,而将其说明为纯虚函数,它的实现留给派生类去做。 格式: virtual类型 函数名 (参数表)=0; 2. 抽象类 是带有纯虚函数的特殊类,主要作用是将有关的子类组织在一个继承层次结构中,由它来为它们提供一个公共的根。

  48. 只能用作其它类的基类,不能建立抽象类对象 • 可说明抽象类指针和引用,指向其派生类,进而实现多态性。 • 不能用作参数类型、函数返回类型或强制转换的类型。 [例6.16]抽象类示例程序

  49. #include <iostream.h> #include <math.h> class base {protected: int x,y; public: virtual void setx(int i,int j=0) {x=i; y=j;} virtual void disp()=0; }; class square: public base {public: void disp() { cout<<x*x<<endl; } }; class cube: public base {public: void disp() { cout<<x*x*x<<endl; } }; class chpow: public base {public: void disp() { cout<<pow(x,y); } }; void main() { base *ptr; square B; cube C; chpow D; ptr=&B; ptr->setx(5); ptr->disp(); ptr=&C; ptr->setx(6); ptr->disp(); ptr=&D; ptr->setx(3,4); ptr->disp(); } 抽象类指针 派生类 抽象类指针指向不同的派生类对象B、C、D,实现多态性

  50. 类名 数据成员 成员函数 6.6 程序举例 vehicle 名称 含义 名称 功能 wheels 车轮个数 vehicle 初始化数据成员 weight 车重 getwheels、getweight 分别获得各数据成员值 print 输出各数据成员值 truck wheels weight 基类vehicle类成员 truck 初始化数据成员的值(通过调用基类的构造函数初始化基类成员) payload 载重量 efficiency 求卡车的载重效率 print 输出数据成员的值(通过调用基类的print函数输出基类成员的值) [例6.17]定义一个汽车类vehicle,其数据成员有车轮个数wheels和车重weight;再定义一个派生类卡车类truck,包含新的数据成员载重量payload及成员函数载重效率。其中: 载重效率=载重量/(载重量+车重)

More Related