面向对象程序设计 QQ群:343072849 Object-Oriented Programming 汽车学院.

Slides:



Advertisements
Similar presentations
C++语言程序设计教程 第5章 构造数据类型 第6章 C++程序的结构.
Advertisements

移动应用软件开发技术 第二讲:C++编程基础
Oracle数据库 Oracle 子程序.
第4章 数组 数组是由一定数目的同类元素顺序排列而成的结构类型数据 一个数组在内存占有一片连续的存储区域 数组名是存储空间的首地址
第14章 c++中的代码重用.
C++中的声音处理 在传统Turbo C环境中,如果想用C语言控制电脑发声,可以用Sound函数。在VC6.6环境中如果想控制电脑发声则采用Beep函数。原型为: Beep(频率,持续时间) , 单位毫秒 暂停程序执行使用Sleep函数 Sleep(持续时间), 单位毫秒 引用这两个函数时,必须包含头文件
第九章 字符串.
Using C++ The Weird Way Something about c++11 & OOP tricks
第4章 函数与预处理 4.1 概述 4.2 定义函数的一般形式 4.3 函数参数和函数的值 4.4 函数的调用 *4.5 内置函数
教材 《C++程序设计》.谭浩强. 清华大学出版社 王雪晶
第五章 模 板.
Chapter 14 Templates.
授课老师:龚涛 信息科学与技术学院 2018年3月 教材: 《Visual C++程序员成长攻略》 《C++ Builder程序员成长攻略》
Object-Oriented Programming in C++ 第一章 C++的初步知识
程序设计期末复习 黎金宁
2 C++ 的基本語法和使用環境 親自撰寫和執行程式是學好程式語言的不二法門。本章藉由兩個簡單的程式,介紹C++ 程式的基本結構和開發環境,讓初學者能逐漸建立使用C++ 的信心。
辅导课程六.
第一单元 初识C程序与C程序开发平台搭建 ---观其大略
C++程序设计 string(字符串类) vector(容器类).
第八章 多态性和虚函数 胡昊 南京大学计算机系软件所.
谭浩强 编著 中国高等院校计算机基础教育课程体系规划教材 C++程序设计.
第十章 模板 丘志杰 电子科技大学 计算机学院 软件学院.
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
切換Dev c++顯示語言 工具->環境選項(V)->介面->language (Chinese TW)
第七章 操作符重载 胡昊 南京大学计算机系软件所.
第一章 函数与极限.
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
C++大学基础教程 第11章 多态性 北京科技大学 信息基础科学系 2019/4/8 北京科技大学.
1.3 C语言的语句和关键字 一、C语言的语句 与其它高级语言一样,C语言也是利用函数体中的可执行 语句,向计算机系统发出操作命令。按照语句功能或构成的不 同,可将C语言的语句分为五类。 goto, return.
C语言程序设计 主讲教师:陆幼利.
第二章 基本数据类型及运算 C数据类型概述 基本数据类型 运算符和表达式 混合运算与类型转换 数据的输入输出 顺序程序设计举例.
简单介绍 用C++实现简单的模板数据结构 ArrayList(数组, 类似std::vector)
C++语言程序设计 C++语言程序设计 第五章 函数 第十一组 C++语言程序设计.
$9 泛型基础.
潘爱民 C++ Overview 潘爱民
C#面向对象程序设计 $6 深入理解类.
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
C++语言程序设计 C++语言程序设计 第三章 控制语句 第十一组 C++语言程序设计.
物件導向程式設計 CH2.
第五章 函 数 要点:掌握函数的定义,函数的原形,函数的返回值,函数的调用,函数的形式参数和实际参数之间的关系;掌握函数重载的使用方法,关键字inline的含义与使用,掌握变量的作用域与生存期,了解函数的作用域。
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
第4章 Excel电子表格制作软件 4.4 函数(一).
C++语言程序设计教程 第2章 数据类型与表达式 第2章 数据类型与表达式 制作人:杨进才 沈显君.
C++程式設計入門 變數與運算子 作者:黃建庭.
C++语言程序设计 C++语言程序设计 第十章 多态 第十一组 C++语言程序设计.
多层循环 Private Sub Command1_Click() Dim i As Integer, j As Integer
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
C++语言程序设计 C++语言程序设计 第八章 继承 C++语言程序设计.
#include <iostream.h>
第7章 模板 陈哲 副教授 南京航空航天大学 计算机科学与技术学院.
C++语言程序设计 C++语言程序设计 第八章 继承 C++语言程序设计.
本节内容 C语言的汇编表示 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
C++语言程序设计 C++语言程序设计 第十一章 异常处理 C++语言程序设计.
C++语言程序设计 C++语言程序设计 第十章 多态 第十一组 C++语言程序设计.
基于列存储的RDF数据管理 朱敏
C++语言程序设计 C++语言程序设计 第一章 C++语言概述 第十一组 C++语言程序设计.
本节内容 动态链接库 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
第三章 高级函数特性.
C++面向对象程序设计 谭浩强编著 授课教师:姬广永 学习网站:
第6章 异常处理 陈哲 副教授 南京航空航天大学 计算机科学与技术学院.
C++语言程序设计 C++语言程序设计 第十章 多态 第十一组 C++语言程序设计.
C++语言程序设计教程 第4章 函数 第4章 函数.
C++语言程序设计 C++语言程序设计 第十一章 异常处理 C++语言程序设计.
變數與資料型態  綠園.
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
C++语言程序设计 C++语言程序设计 第二章 基本数据类型与表达式 第十一组 C++语言程序设计.
Presentation transcript:

面向对象程序设计 QQ群:343072849 Object-Oriented Programming 汽车学院

面向对象的程序设计 本章主要内容: 模板概念 函数模板与模板函数 类模板与模板类 异常处理 异常处理概述 异常处理方法 2/21

第6章 模板与异常处理 6.1 模板的概念 6.2 函数模板与模板函数 6.3 类模板与模板类 6.4 异常处理 6.5 应用举例

6.1 模板的概念 C++ 语言的核心优势之一就是便于软件的重用 C++中有两个方面体现重用: 1. 面向对象的思想:继承和多态 2. 模板机制

如果能使这些函数只写一遍,即写一个通用的函数,适用于不同数据类型,便会大大提高代码的可重用性。C++的模板可以解决这一问题。 6.1 模板的概念 int max(int x,int y) { return (x>y)?x:y;} long max(long x,long y) double max(double x,double y) char max(char x, char y) 这些函数函数体都一样,但由于所处理的参数类型和返回值不同,所以是完全不同的函数。虽然可以通过重载使它们有相同的函数名,但还是得为每个函数写一组代码。 如果能使这些函数只写一遍,即写一个通用的函数,适用于不同数据类型,便会大大提高代码的可重用性。C++的模板可以解决这一问题。

6.1 模板的概念 ‡ 若一个程序的功能是对某种特定的数据类型进行处理,则可以将所处理的数据类型说明为参数,以便在其他数据类型的情况下使用,这就是模板的由来。 ‡ 模板是以一种完全通用的方法来设计函数或类而不必预先说明将被使用的每个对象的类型。 ‡ 通过模板可以产生类或函数的集合,使它们操作不同的数据类型,从而避免需要为每一种数据类型产生一个单独的类或函数。

6.1 模板的概念 模板是实现代码重用机制的一种工具,它可以实现类型参数化,即把类型定义为参数,从而实现了真正的代码重用。 模板分为函数模板和类模板,它们分别允许用户构造模板函数和模板类。

6.1 模板的概念 模板分类 ‡ 函数模板(function template) „ 是独立于类型的函数 „ 可产生函数的特定版本 ‡ 类模板(class template) „ 跟类相关的模板 „ 可产生类对特定类型的版本

模板 (函数模板和类模板) 模板函数 模板类 对象 6.1 模板的概念 模板 (函数模板和类模板) 实例化 实例化 模板函数 模板类 实例化 对象

第6章 模板与异常处理 6.1 模板的概念 6.2 函数模板与模板函数 6.3 类模板与模板类 6.4 异常处理 6.5 应用举例

6.2 函数模板与模板函数 函数模板的说明 建立一个通用函数,其函数返回类型与形参类型不具体指定,由虚拟类型来代表。这个通用函数就称为函数模板。 函数模板的一般说明形式如下: template <typeName 类型参数>或 template <class 类型参数> 返回类型 函数名(模板形参表) { 函数体 } 关键字template: 表示正在声明一个模板 关键字typename: 表示其后的参数是一个虚拟的类型名 类型参数(通常用T,Type等):虚拟的类型名

6.2 函数模板与模板函数 例如:将求最大值函数max()定义成函数模板,如下所示: template < typename T> T max(T x,T y) { return (x>y)?x:y; } 也可以定义成如下形式: template < class T> 其中,T为类型参数,它既可取系统预定义的数据类型,又可以取用户自定义的类型。

6.2 函数模板与模板函数 使用函数模板时,关键字typename(或class)后面的类型参数必须用实际的数据类型替代它。 当编译系统发现有一个函数调用: 函数名(模板实参表); 函数模板经实例化生成的具体函数叫模板函数。该模板函数的函数体与函数模板的函数定义体相同。 函数模板代表一类函数,模板函数表示某一具体函数

6.2 函数模板与模板函数 例6.1 函数模板的使用。//p261 #include <iostream> using namespace std; template < typename AT> AT max(AT x,AT y) { return (x>y) ? x:y; } int main() { int i1= 10, i2=50; double d1=50.344, d2=4656.346; char c1='k ',c2='n'; cout<<"The max of i1, i2 is: "<<max(i1,i2) <<endl; cout<<"The max of d1, d2 is: "<<max(d1,d2) <<endl; cout<<"The max of c1, c2 is: "<<max(c1,c2) <<endl; return 0; } AT:类型参数 模板声明,定义函数模板 模板实参

6.2 函数模板与模板函数 例6.2 有关指针的函数模板 //p263 using namespace std; #include <iostream> using namespace std; template <typename T> T sum(T *array, int size=0) { T total=0; for (int i=0; i<size; i++) total+=array[i]; return total; } int int_array[ ]={1,2,3,4,5,6,7,8,9 ,10}; double double_array[ ]={1.1,2.2,3.3,4.4,5.5,6.6,7.7,8.8,9.9,10.10}; int main() { int itotal=sum(int_array, 10) ; double dtotal=sum(double_array, 10) ; cout<<"itotal=" <<itotal <<endl; cout<<"dtotal=" <<dtotal <<endl; return 0; }

6.2 函数模板与模板函数 说 明 在template语句与函数模板定义语句之间不能有别的语句。 说 明 在template语句与函数模板定义语句之间不能有别的语句。 template <class T> int i; // 错误 T max(T x,T y) { return (x>y)?x:y; } 模板函数类似于重载函数, 只不过它更严格一些。在函数重载时,每个函数体可以执行不同的动作。但同一函数模板实例化后的所有模板函数都必须执行相同的动作。 在函数模板中允许使用多个类型参数, 每个类型参数前必须有关键字class/typename。

6.2 函数模板与模板函数 #include<iostream> using namespace std; template<typename type1, typename type2> void myfunc(type1 x, type2 y) { cout<<x<<" "<<y<<endl; } int main() myfunc(10, "hao"); myfunc(0.123, 10L); return 0;

6.2 函数模板与模板函数 4. 同一般函数一样,函数模板也可以重载. 定义2个类型参数的函数模板max 定义3个类型参数的函数模板max 4. 同一般函数一样,函数模板也可以重载. 例6.4:#include<iostream.h> //p264 template<typename type> type max(type x, type y) { return (x>y)?x:y; } type max(type x, type y , type z) { type t; t= (x>y)?x:y ; return (t>z)?t:z ; } int main() { int m=10,n=20,max2; double a=10.1,b=20.2,c=30.3,max3; max2=max(m,n); max3=max(a,b,c); cout<<"max("<<m<<","<<n<<")="<<max2<<endl; cout<<"max("<<a<<","<<b<<","<<c<<")=" <<max3<<endl; return 0;} 定义2个类型参数的函数模板max 定义3个类型参数的函数模板max 调用模板函数max

6.2 函数模板与模板函数 函数模板与同名的非模板函数可以重载. 例6.5: 函数模板与同名的非模板函数可以重载. 例6.5: #include<iostream.h> //p265 template<typename AT> AT max(AT x, AT y) { cout<<“调用模板函数:”; return (x>y)?x:y; } int max(int x, int y) { cout<<“调用非模板函数:”; return (x>y)?x:y; } int main() { int i1=10,i2=20; double d1=10.1,d2=20.2; char c1=‘k’,c2=‘n’; cout<<"较小的整数是:"<<max(i1,i2)<<endl; cout<<"较小的双精度数是:"<<max(d1,d2)<<endl; cout<<"较小的字符串是:"<<max(c1,c2)<<endl; return 0; }

6.2 函数模板与模板函数 在C++中, 函数模板和同名的非模板函数重载时,调用的顺序遵循以下约定: 1) 寻找一个参数完全匹配的函数, 如果有则调用之。 2) 寻找一个函数模板, 将其实例化,产生一个匹配的模板函数, 若匹配则调用之。 3) 若1步和2步都失败, 就再试低一级的对函数调用方法,例如通过类型转换可产生参数匹配等。 若找到了则调用之。 4) 若1步2步3步都未找到匹配的参数,则返回一个错误的调用。 5) 若在1步有多于一个的选择, 即函数调用存在二义性,则也是错误的调用。

第6章 模板与异常处理 6.1 模板的概念 6.2 函数模板与模板函数 6.3 类模板与模板类 6.4 异常处理 6.5 应用举例

6.3 类模板与模板类 类模板:建立一个通用类,其数据成员、成员函数的返回类型和形参类型不具体指定,用一个虚拟的类型来代替。 使用类模板定义对象时,系统根据实参的类型来取代类模板中虚拟类型从而实现不同的功能。

定义一个类模板与定义函数模板的格式类似,必须以关键字template开始,然后是类名,其格式如下: 6.3 类模板与模板类 定义一个类模板与定义函数模板的格式类似,必须以关键字template开始,然后是类名,其格式如下: template <typename[或class] 类型参数> class 类名 { //… }; 模板参数 类型参数 如Type ‹<类型参数>与函数模板中的意思相同,是一个虚拟类型名 ‹类成员的声明方法同普通类的定义,只是各个成员(数据和函数)可以用模板的通用类型参数

在类定义中, 欲采用通用数据类型的数据成员, 成员函数的参数或返回值前面需要加上Type。 6.3 类模板与模板类 const int size=10; template <class Type> class stack { public: void init(){ tos=0; } void push (Type ch); Type pop( ); private: Type stck[size]; int tos; }; 在类定义中, 欲采用通用数据类型的数据成员, 成员函数的参数或返回值前面需要加上Type。

在类体外定义有类型参数的成员函数时, 需要在函数体外进行模板声明, 并且在函数名前的类名后加上“<Type>” 6.3 类模板与模板类 在类体外定义有类型参数的成员函数时, 需要在函数体外进行模板声明, 并且在函数名前的类名后加上“<Type>” template <class Type> void stack<Type>::push(Type ob) { if (tos==size) { cout<<"stack is full "; return; } stck[tos]=ob; tos++;

在类体外定义有类型参数的成员函数时, 需要在函数体外进行模板声明, 并且在函数名前的类名后加上“<Type>” 6.3 类模板与模板类 在类体外定义有类型参数的成员函数时, 需要在函数体外进行模板声明, 并且在函数名前的类名后加上“<Type>” template <class Type> Type stack<Type>::pop( ) { if (tos==0) { cout<<"stack is empty "; return 0; } tos - -; return stck[tos];

6.3 类模板与模板类 类模板不是代表一个具体的、实际的类, 而是代表着一类类。实际上, 类模板的使用就是将类模板实例化成一个具体的类, 它的格式为: 类模板名 <实际的类型> 对象名; 例: stack <char> s1, s2;

6.3 类模板与模板类 例6.8 使用栈类模板 //p269 #include<iostream> using namespace std; const int size=10; template<class Type> //声明一个类模板 class stack{ public: void init(){ tos=0; } void push(Type ch); //参数取Type类型 Type pop(); //返回类型取Type类型 private: Type stck[size]; //数组的类型为类型参数Type, //即可取任意类型 int tos; }; template <class Type> void stack<Type>::push(Type ob) { // ...... }

6.3 类模板与模板类 template <class Type> Type stack <Type>::pop() { // ... ... } int main() { //定义字符堆栈 stack <char> s; //创建模板参数为char型的对象 int i; s.init(); s.push('a'); s.push('b'); s.push('c'); for(i=0;i<3;i++) cout<<"pop s: "<<s.pop()<<endl;

6.3 类模板与模板类 //定义整型堆栈 stack <int> is; //创建模板参数为int型的对象 is.init(); is.push(1); is.push(3); is.push(5); for (i=0;i<3;i++) cout<<"pop is: "<<is.pop()<<endl; return 0; } #include<iostream> using namespace std; const int size=10; template<class Type> //声明一个类模板 class stack{ public: void init(){ tos=0; } void push(Type ch); //参数取Type类型 Type pop(); //返回类型取Type类型 private: Type stck[size]; //数组的类型为类型参数Type, 即可取任意类型 int tos; }; template <class Type> void stack<Type>::push(Type ob) { if(tos==size) cout<<"Stack is full"; return; } stck[tos]=ob; tos++; Type stack <Type>::pop() if(tos==0) {cout<<"Stack is empty"; return 0;} tos--; return stck[tos]; int main() { //定义字符堆栈 stack <char> s; //创建模板参数为char型的对象 int i; s.init(); s.push('a'); s.push('b'); s.push('c'); for(i=0;i<3;i++) cout<<"pop s: "<<s.pop()<<endl; //定义整型堆栈 stack <int> is; //创建模板参数为int型的对象 is.init(); is.push(1); is.push(3); is.push(5); for (i=0;i<3;i++) cout<<"pop is: "<<is.pop()<<endl; return 0;

6.3 类模板与模板类 类模板 stack <Type> 模板类 stack <char> stack <int> stack <double> 实例化 对象s 对象is 对象ds

6.3 类模板与模板类 说明 在每个类模板定义之前, 都需要在前面加上模板声明: template <class Type> class stack { ... ... 类模板在使用时, 必须在类名后面缀上模板参数<Type>: stack <Type> s1, s2; 模板类可以有多个类型参数.

6.3 类模板与模板类 例6.9 使用两个类型参数的类模板 //p272 #include<iostream> using namespace std; template<class T1, class T2> class myclass{ public: myclass (T1 a, T2 b){i=a; j=b;} void show() {cout<<"i="<<i<<"j="<<j<<endl;} private: T1 i; T2 j; }; int main ( ) { myclass <int, double> ob1(12, 0.15); myclass <char,char*> ob2('x',"Test"); ob1.show(); ob2.show(); return 0; } #include<iostream> using namespace std; template<class T1, class T2> class myclass{ public: myclass (T1 a, T2 b){i=a; j=b;} void show() {cout<<"i="<<i<<"j="<<j<<endl;} private: T1 i; T2 j; }; int main ( ) { myclass <int, double> ob1(12, 0.15); myclass <char,char*> ob2('x',"Test"); ob1.show(); ob2.show(); return 0; }

第6章 模板与异常处理 6.1 模板的概念 6.2 函数模板与模板函数 6.3 类模板与模板类 6.4 异常处理 6.5 应用举例

6.4 异常处理 6.4.1 异常处理概述 6.4.2 异常处理的方法

6.4.1 异常处理概述 1、常见的错误分为两大类: 1)编译时的错误 例如:关键字拼写错误、语句末尾缺分号、括 号不匹配等。 例如:关键字拼写错误、语句末尾缺分号、括 号不匹配等。 这类错误相对容易修正。 2)运行时的错误 例如:无法打开输出文件、数组下标越界等。 这类错误较隐蔽,不易被发现。 2、运行过程中出现的错误统称为异常,对异常的处理称为异常处理。传统异常的处理方法基本上是采取判断语句或分支语句来实现。

6.4.1 异常处理概述 例6.10 传统的异常处理方法举例.P273 #include<iostream> using namespace std; int Div(int x, int y); int main() { cout<<"7/3 = "<<Div(7, 3)<<endl; cout<<"5/0 = "<<Div(5, 0)<<endl; return 0; } int Div(int x, int y) if(y == 0) cout<<"除数为0,错误!"<<endl; exit(0); return x/y;

6.4 异常处理 6.4.1 异常处理概述 6.4.2 异常处理的方法

6.4.2 异常处理的方法 C++异常处理办法: 如果在执行一个函数过程中出现异常,可以不在本函数中立即处理,而是发出一个信息,传给它的上一级(即调用函数)来解决,如果上一级函数也不能处理,就再传给其上一级处理。如此逐级上传,如果到最高一层还无法处理,运行系统一般会自动调用系统函数terminate,用它调用abort终止函数。

6.4.2 异常处理的方法 C++异常处理办法: C++处理异常的机制由检查、抛出和捕获3个部分组成,分别由3种语句来完成:try(检查)、throw(抛出)和catch(捕获)。

6.4.2 异常处理的方法 1、异常的抛出 抛出异常格式: throw 表达式; 例如: int Div(int x, int y) { if(y == 0) throw y; //抛出异常,当除数为0时,语句throw将抛出int型异常 return x/y; } 若某段程序出现异常,可用throw抛出异常给调用者,由与之匹配的catch捕获。throw中的表达式表示抛出的异常类型,由表达式的类型来表示。

6.4.2 异常处理的方法 2、异常的检测和捕获 检测和捕获的格式: try{被检查的复合语句;} catch(异常类型声明1) {进行异常处理的复合语句1} catch(异常类型声明2) {进行异常处理的复合语句2} . catch(异常类型声明n) {进行异常处理的复合语句n}

6.4.2 异常处理的方法 例6.11 处理除数为0的异常的程序. P276 #include<iostream> using namespace std; int Div(int x, int y); int main() { try{ cout<<"7/3 = "<<Div(7, 3)<<endl; cout<<"5/0 = "<<Div(5, 0)<<endl; } catch(int){ cout<<"除数为0,错误!"<<endl; } return 0; int Div(int x, int y) if(y == 0) throw y; return x/y;

6.4.2 异常处理的方法 说明 被检测的语句或程序段必须放在try中,否则不起作用。 try和catch块中的花括号必须有,即使括号内只有一条语句也不能省。 一个try_catch结构中只能有一个try块,但可以有多个catch块,以便于不同的异常信息匹配。catch后面括号中一般只写异常信息的类型名。

6.4.2 异常处理的方法 例6.12 有多个catch块的异常处理程序 #include<iostream> using namespace std; int main() { double a = 2.5; try{ throw a; } catch (int ) {cout<<"异常发生!整数型!"<<endl;} catch (double ) {cout<<"异常发生!双精度型!"<<endl;} cout<<"end"<<endl; return 0; }

6.4.2 异常处理的方法 4.如果在catch子句中没有指定异常信息的类型,而用了三点删节号“...”,则表示它可以捕获任何类型的异常信息。 例6.13 有“...”删节号的异常处理程序 #include<iostream> using namespace std; int main() { double a = 2.5; try{ throw a; } catch (int ) {cout<<"异常发生!整数型!"<<endl;} catch (...) {cout<<"任意类型异常!"<<endl;} cout<<"end"<<endl; return 0; }

6.4.2 异常处理的方法 5.在某种情况下,在throw语句中可以不包括表达式,如: throw; 6.C++中,一旦抛出一个异常,而程序又不捕获的话,那么系统就会调用一个系统函数terminate,由它调用abort终止程序。

第6章 模板与异常处理 6.1 模板的概念 6.2 函数模板与模板函数 6.3 类模板与模板类 6.4 异常处理 6.5 应用举例

6.5 应用举例 自学:P278-282。

Practice, Practice, and Practice Q & A Practice, Practice, and Practice Object-Oriented Programming 汽车学院