案例讨论:时间类该sum函数

advertisement
C++ Programming
Lecture 16
Wei Liu (刘威)
Dept. of Electronics and Information Eng.
Huazhong University of Science and Technology
Feb. 2014
Lecture 16

Chapter 19. Operator Overloading















19.1 Introduction
19.2 Fundamentals of Operator Overloading
19.3 Restrictions on Operator Overloading
19.4 Operator Functions as Class Members vs. Global Functions
19.5 Overloading Stream Insertion and Stream Extraction Operators
19.6 Overloading Unary Operators
19.7 Overloading Binary Operators
19.8 Dynamic Memory Management
19.9 Case Study: Array Class
19.10 Converting between Types
19.11 Case Study: String Class
19.12 Overloading ++ and -19.13 Case Study: A Date Class
19.14 Standard Library Class string
19.15 explicit Constructors
-2-
Chapter 19. Operator Overloading

运算符重载



对特定的类定义相应的运算符的功能
通过函数来实现
学习要点



实现对象运算的成员函数如何设计?
运算符重载的成员函数如何定义?如何调用?
运算符重载的全局函数如何定义?如何调用?
-3-
案例讨论:时间类
operator1.cpp
…
show函数输出“xx:xx”的字符信息
strstream是C++标准string流处理类,该类可以接
受流式输入,也可以转换为特定类型的对象输出
-4-
案例讨论:时间类
operator1.cpp
形参是对象的引用,降低传递的开销
函数sum是const表示不会修改对象this
设计sum函数,完成两个time对象相加的功能:
result = this + more
对象more是函数sum的一个参数
对象result是由函数sum创建的临时对象
-5-
案例讨论:时间类
operator1.cpp
-6-
案例讨论:时间类
operator1.cpp
该sum函数返回值只能设为 Time对象,而不能是对象的引用。Why?
operator2.cpp
-7-
案例讨论:时间类
operator1.cpp
该sum函数,可以改造成等效的运算符重载函数operator+
operator3.cpp
-8-
案例讨论:时间类
operator3.cpp
operator+可以显式的以函数调
用的形式调用: a.operator+(b)
operator+也可以用表达式的形
式调用: a+b
operator+的函数调用方式参考
运算符+的结合性来展开
受限于函数调用关系,对象a的成员函数operator+只能支持
a + b 形式的函数调用,不能支持 b + a 形式的函数调用
如果希望表达式的第一个操作数可以不是对象,则需要采用
全局函数的方法
-9-
案例讨论:时间类
operator4.cpp
Time * int_k 的表达式
用Time类的成员函数重载
operator* 来实现,该函数
的参数是int_k
int_k * Time 的表达式
用Time类的全局友元函数重载
operator* 来实现,该函数的参
数分别是int_k , Time_t
-10-
案例讨论:时间类
operator4.cpp
Time成员函数重载运算符,支
持Time * int_k 的表达式
Time的全局友元函数重载运算
符,支持int_k * Time 的表达
式
-11-
小结

运算符重载的学习要点

实现对象运算的成员函数如何设计?
 返回值可以是一个对象。函数调用完毕后,该对象将以函数返回值的形
式复制给主调函数的接受对象。
 返回值可以是一个引用。但是该引用必须能在函数调用完毕后有意义,
即不能使“悬挂引用”

运算符重载的成员函数如何定义?如何调用?
 二元运算符重载时,该函数只需要接收另一个对象more作为参数
 调用该函数时,this对象出现在运算符左边,more对象出现在右边

运算符重载的全局函数如何定义?如何调用?
 二元运算符重载时,该函数需要接收两个对象作为参数
 调用该函数时,第一个实参在运算符左边,第二个实参在右边
-12-
Experiment

改写Time类,重载运算符,支持时间的相减运算



1. 采用成员函数
2. 采用全局友元函数
3. 采用全局非友元函数
Lecture 16

Chapter 19. Operator Overloading















19.1 Introduction
19.2 Fundamentals of Operator Overloading
19.3 Restrictions on Operator Overloading
19.4 Operator Functions as Class Members vs. Global Functions
19.5 Overloading Stream Insertion and Stream Extraction Operators
19.6 Overloading Unary Operators
19.7 Overloading Binary Operators
19.8 Dynamic Memory Management
19.9 Case Study: Array Class
19.10 Converting between Types
19.11 Case Study: String Class
19.12 Overloading ++ and -19.13 Case Study: A Date Class
19.14 Standard Library Class string
19.15 explicit Constructors
-14-
19.2 Fundamentals

Three exceptions in operator overloading 要对类的对象使用运算符,
就需要运算符重载,三种例外情况是:


The assignment operator (=) may be used with every class to perform
memberwise assignment of the class’s data members. 赋值运算符无需重载
The address (&) and comma (,) operators may also be used with objects of any
class without overloading. 取地址和逗号运算符无需重载
-15-
19.3 Restrictions

Restrictions

The precedence of an operator cannot be changed 重载不能
改变运算符的优先级

The associativity of an operator (i.e., whether the operator
is applied right-to-left or left-to-right) cannot be changed 重
载不能改变运算符的结合律

It isn’t possible to change the “arity” of an operator 重载不
能改变运算符的元数

相关的运算符不会自动重载


= vs. +=
== vs. !=
-16-
19.4 Operator Functions as Class Members
vs. Global Functions
Class Members成员函数
Global Functions全局函数
参数调用
用this指针隐式的获得一个类的
对象的实参,即二元运算符的第
一个操作数
用显式的方式获得二元运算符的
两个操作数
函数调用
最左侧的操作数必须是该运算符
所属类的对象
如果左操作数必须是其它类的对
象或者基本类型对象(例如int,
double),则运算符函数必须实
现为全局函数
如果必须直接访问private或者
protected成员,则该函数必须
是该类的友元函数
重载限制
必须重载为类的成员的运算符:
( ) [ ] -> = += -=
下列运算符通常重载为全局函数:
<< >>
-17-
Lecture 16

Chapter 19. Operator Overloading















19.1 Introduction
19.2 Fundamentals of Operator Overloading
19.3 Restrictions on Operator Overloading
19.4 Operator Functions as Class Members vs. Global Functions
19.5 Overloading Stream Insertion and Stream Extraction Operators
19.6 Overloading Unary Operators
19.7 Overloading Binary Operators
19.8 Dynamic Memory Management
19.9 Case Study: Array Class
19.10 Converting between Types
19.11 Case Study: String Class
19.12 Overloading ++ and -19.13 Case Study: A Date Class
19.14 Standard Library Class string
19.15 explicit Constructors
-18-
11.8 Dynamic Memory Management

dynamic memory management 动态内存分配
 C++ enables you to control the allocation and deallocation.
 performed with operator new and delete.

new operator 获得动态内存
 to dynamically allocate (i.e., reserve) the exact amount of
memory required to hold an object or array at execution time.
 The object or array is created in the free store (also called the
heap)—a region of memory assigned to each program for
storing dynamically allocated objects.

delete operator 释放动态内存
 You can return memory to the free store by using the delete
operator to deallocate it.
-19-
案例讨论:时间类
operator6.cpp
在Time构造和析构函数中增加
打印信息
可以观察到表达式运算过
程中临时对象的创建和销
毁
-20-
案例讨论:时间类
operator7.cpp
采用new[ ]动态创建Time数组
时,只能采用默认构造函数
可以观察到表达式运算过采用
new[ ]动态创建的对象数组,需
要用delete[ ] 释放相应的内存
-21-
11.9 Case Study: Array Class

In this example, we create a powerful Array class:
 Performs range checking. 支持下标边界检查
 Allows one array object to be as-signed to another with the
assignment operator. 支持数组直接赋值
 Objects know their own size. 数组知道自己的大小
 Input or output entire arrays with the stream extraction and
stream insertion operators, respectively. 数组可以整体输
入和输出
 Can compare Arrays with the equality operators ==
and !=. 数组可以整体进行比较

C++ Standard Library class template vector provides many
of these capabilities as well.
-22-
uses new to obtain the
memory for the internal
pointer-based representation
of this array and assigns the
pointer returned by new to
data member ptr
uses delete [] to release the memory
allocated dynamically by new in the constructor.
When the compiler sees the expression
integers1 = integers2, the
compiler invokes member function
operator= with the call
integers1.operator=(integer
s2)
returning the current object (i.e., *this
as a constant reference; this enables
cascaded Array assignments such as
x=y=z
When the compiler sees the expression
integers1 == integers2, the compiler
invokes member function operator==
with the call
integers1.operator==(integers2
)
When the compiler sees the expression
integers1[5] it invokes the
appropriate overloaded operator[]
member function by gener-ating the call
integers1.operator[]( 5 )
If the subscript is in range, the non-const
version of operator[] returns the
appropriate array element as a reference so
that it may be used as a modifiable lvalue.
If the subscript is in range, the const
version of operator[] returns a copy
of the appropriate element of the array.
These stream insertion and stream extraction operator functions cannot be
members of class Array, because the Array object is always mentioned on
the right side of the stream insertion operator and the stream extraction
operator.
Lecture 16

Chapter 19. Operator Overloading















19.1 Introduction
19.2 Fundamentals of Operator Overloading
19.3 Restrictions on Operator Overloading
19.4 Operator Functions as Class Members vs. Global Functions
19.5 Overloading Stream Insertion and Stream Extraction Operators
19.6 Overloading Unary Operators
19.7 Overloading Binary Operators
19.8 Dynamic Memory Management
19.9 Case Study: Array Class
19.10 Converting between Types
19.11 Case Study: String Class
19.12 Overloading ++ and -19.13 Case Study: A Date Class
19.14 Standard Library Class string
19.15 explicit Constructors
-30-
19.14 Standard Library Class string
-31-
-32-
-33-
-34-
-35-
Lecture 16

Chapter 20. Object-Oriented Programming: Inheritance







20.1 Introduction
20.2 Base Classes and Derived Classes
20.3 protected Members
20.4 Relationship between Base Classes and Derived Classes
20.5 Constructors and Destructors in Derived Classes
20.6 public, protected and private Inheritance
20.7 Software Engineering with Inheritance
-36-
20.1 Introduction





Inheritance is a form of software reuse in which you create a
class that absorbs an existing class’s data and behaviors and
enhances them with new capabilities.
You can designate that the new class should inherit the
members of an existing class.
继承是一种软件重用的方式。如果现有类可以描述事物的
现有数据和行为,通过继承来获得和增强类的能力
This existing class is called the base class, and the new class is
referred to as the derived class.
现有的类被称为基类,从基类继承出来的类被称为派生类
-37-
Student
+ int id;
+ string name;
+ float score;
- char gender;
Student
+ Student()
+ display()
Graduate
Master
硕士研究生
学生
研究生
Ph.D
博士研究生
Graduate
+ int id;
+ string name;
+ float score;
- char gender;
- float pay;
+ Graduate()
+ display()
-38-
Class of student : student.h
Protected 表示数据成员可以被继承
Priviate 表示数据成员在继承时将被隐藏,
不能直接访问
-39-
Class of student : studend.cpp
-40-
Class of graduate: graduate.h
表示继承Student类的所有公共属性
派生类可以创建新的数据成员、新的成员函数、改写基类的成员函数
基类的数据成员和成员函数都自动地可以被派生类访问
-41-
Class of graduate: graduate.cpp
派生类访问基类的成员函数需要用域说明符::
-42-
Using inheritance
-43-
Advanced programming (1)

Default arguments in constructor

Calling parent constructor in child class
派生类不必使用基类的全部数据成员
-44-
Advanced programming (2)

Visiting protected / private data members of
parent class
派生类不能访问基类的私有数据成员
派生类可以通过访问基类的公共成员函数来间接获取私有数据成员的值
-45-
作业

19.9 实现超大整数HugeInt类的运算符重载
设计一个基类Event和两个派生类Meeting,Lecture,
编写测试程序验证其功能





Event类描述时间、地点、事件;
Meeting类描述时间、地点、会议议程、参会人员;
Lecture类描述时间、教室地点、授课教师、课程名称、授
课内容
预习多态,结合上面的题目,编写基类和派生类的
display()函数,展示多态性
-46-
谢谢!
刘威 副教授
互联网技术与工程研究中心
华中科技大学电子与信息工程系
电话:13986224922
Email: liuwei@hust.edu.cn
网址:http://itec.hust.edu.cn
Download