Classes (2) Lecture 7.

Slides:



Advertisements
Similar presentations
6. 6 Overloading methods and constructors 6
Advertisements

Memory Pool ACM Yanqing Peng.
设计模式可以帮助我们改善系统的设计,增强 系统的健壮性、可扩展性,为以后铺平道路。
程設一.
第八章 类和对象.
第9章 单例模式 Website:
C# 程式設計 第一部分 第1-4章 C# 程式設計 - 南華大學資管系.
Chapter 7 Search.
走向C++之路 WindyWinter WindyWinter感谢诸位前来捧场。
struct 可以在同一個名稱下擁有多種資料型態。使用struct能讓資料的存取和處理更為靈活。
Chap 18 類別與物件 夫有土者,有大物也。有大物者,不可以物。 物而不物,故能物物。 明乎物物者之非物也,豈獨治天下百姓而已哉!
Derived Class 前言 衍生類別的定義 單一繼承 public, protected, 和 privated 基底類別
C++程序设计 第二讲 清华大学软件学院.
刘胥影 东南大学计算机学院 面向对象程序设计1 2011~2012第3学期 刘胥影 东南大学计算机学院.
Classes Lecturer: 曾學文.
Scope & Lifetime 前言 Local Scope Global Functions & Objects
第11章 运算符重载 什么是运算符重载 运算符重载的方法 几个特殊的运算符的重载 自定义类型转换运算符 运算符重载实例.
刘胥影 东南大学计算机学院 面向对象程序设计1 2011~2012第3学期 刘胥影 东南大学计算机学院.
第七章 搜索结构 静态搜索结构 二叉搜索树 AVL树.
·线性表的定义及ADT ·线性表的顺序存储结构 ·线性表的链接存储结构 · 单向循环链表 · 双链表、双向循环链表 · 一元多项式的加法
Classes: A Deeper Look, Part 1
第六章 继承性和派生类 胡昊 南京大学计算机系软件所.
创建型设计模式.
刘胥影 东南大学计算机学院 面向对象程序设计1 2010~2011第3学期 刘胥影 东南大学计算机学院.
Object-Oriented Programming:
Operator Overloading; String and Array Objects
西安交通大学 计算机教学实验中心 大学C++程序设计教程 西安交通大学 计算机教学实验中心
授课老师:龚涛 信息科学与技术学院 2018年3月 教材: 《Visual C++程序员成长攻略》 《C++ Builder程序员成长攻略》
Object-Oriented Programming in C++ 第一章 C++的初步知识
程序设计期末复习 黎金宁
第三章 C++中的C 面向对象程序设计(C++).
第12章 從C到C++語言 12-1 C++語言的基礎 12-2 C++語言的輸出與輸入 12-3 C++語言的動態記憶體配置
2 C++ 的基本語法和使用環境 親自撰寫和執行程式是學好程式語言的不二法門。本章藉由兩個簡單的程式,介紹C++ 程式的基本結構和開發環境,讓初學者能逐漸建立使用C++ 的信心。
C 語言簡介 - 2.
第3章 變數、常數與資料型態 3-1 C語言的識別字 3-2 變數的宣告與初值 3-3 指定敘述 3-4 C語言的資料型態
第6章 基本的IDL到C++的映射 3.2 简介 从IDL到C++的映射必须具备下面的条件 (1) 映射应该很直观,并且很容易使用
第九單元 Classes and data abstraction I
类类型 C++支持的内置类型和操作,如 int i=10; i=i%6; i=i+4;
10 多載函數 10.1 多載概論 多載一般函數 多載成員函數 10-3
Chapter 5 Recursion.
C++程序语言设计 Chapter 3: The C in C++.
第十三讲 文件流与 输出输入重载.
第14章 输入输出与文件 输入输出是指程序与外部设备交换信息 C++把输入输出看成是一个数据流 输入流:外围设备流向内存的数据
第三章 链表 单链表 循环链表 多项式及其相加 双向链表 稀疏矩阵.
第3章 Java語法的JSP程式 3-1 Java語言的基礎 3-2 JSP程式的基本架構 3-3 Java的變數與資料型態
常宝宝 北京大学计算机科学与技术系 数据结构(三) 常宝宝 北京大学计算机科学与技术系
第五章 递归与广义表 递归的概念 递归过程与递归工作栈 递归与回溯 广义表.
An Introduction to Object-Oriented Programming Using C++
潘爱民 C++ Overview 潘爱民
Speaker: Liu Yu-Jiun Date: 2009/4/29
Classes (1) Lecture 6.
top b top a a top 空栈 a 进栈 b 进栈 top top e e e top d d d c c c b b b a a
OOP Recitation Course Speaker: Liu Yu-Jiun Date: 2009/3/25.
第四章 栈和队列 栈 ( Stack ) 队列 ( Queue ) 优先队列 (Priority Queue) 小结.
Speaker: Liu Yu-Jiun Date: 2009/5/6
Inheritance -II.
第三章 数据抽象.
C++程序设计 吉林大学计算机科学与技术(软件)学院.
第1章 C++面向对象程序设计要点 1.1 函数和函数参数 1.2 输入输出   1.3 类 1.4 抽象类型和模板.
授课老师:龚涛 信息科学与技术学院 2016年3月 教材:《Visual C++程序员成长攻略》 《C++ Builder程序员成长攻略》
第 8 章 标准模板库STL 陈哲 副教授 南京航空航天大学 计算机科学与技术学院.
第 3 章 类的基础部分 陈哲 副教授 南京航空航天大学 计算机科学与技术学院.
#include <iostream.h>
第二章 Java基本语法 讲师:复凡.
第一讲 面向对象方法学与信息系统建模.
2012 程式設計比賽 Openfind 天使帝國 v2.0 (蓋亞的紋章).
本章主題 C++的程式結構 資料型態與宣告 算術運算 簡易的輸入輸出指令 程式編譯(Compile)的過程與原理.
《数据结构与算法设计》第一部分 面向对象的C++程序设计基础.
JAVA 程式設計與資料結構 第三章 物件的設計.
對於成員(member)存取權的限制 成員的資料被毫無限制的存取,任誰都可以指定任意值給成員,Java語言為了防止這種現象的產生,規定:有一種成員的資料不能任由類別外部的任何人隨意存取。
Presentation transcript:

Classes (2) Lecture 7

Basic concepts Overloaded operators are functions with special names: the keyword operator followed by the symbol for the operator being defined. 3 + 4 + 3 4 3 4 + operator+ (3, 4) conventional notation 5 * (3 + 4) * 5 + 3 4 5 3 4 + * operator* (5, operator+ (3, 4)) Polish notation reverse Polish notation functions

Basic concepts [RECALL] Overloaded functions are functions that have the same name but different parameter lists and that appear in the same scope are overloaded. (Lecture 5) [NOTE] An operator function must either be a member of a class or have at least one parameter of class type. implicit this pointer It is illegal to (re-)define operators for built-in types.

Recall operator<< class Sales_item { public: friend ostream& operator<< (ostream &out, const Sales_item &item) { out << item.isbn << “, $“ << item.revenue << “, “ << item.units_sold; return out; } private: string isbn; double revenue; unsigned int units_sold; };

Overloading operator>> cannot be const class Sales_item { public: friend istream& operator>> (istream &in, Sales_item &item) { in >> item.isbn >> item.revenue >> item.units_sold; return in; } }; must be friend Sales_item item; cin >> item; cout << item; 978-0-321-71411-4 569.9 10 978-0-321-71411-4, $569.9, 10

File IO Sales_item item; ifstream fin(“data.txt”); Tested on macOS High Sierra ver. 10.13.6 with GCC ver. 4.2.1 [Nov 22, 2018] File IO Sales_item item; ifstream fin(“data.txt”); if (!fin.is_open( )) return 1; ofstream iout(“items.txt”); ofstream pout(“prices.txt”); while (!fin.eof( )) { fin >> item; iout << item << endl; pout << item.get_isbn( ) << “: $” << item.avg_price( ) << endl; } fin.close( ); iout.close( ); pout.close( ); return 0; 打开输入文件 判断是否打开成功 data.txt 978-0-321-71411-4 569.9 10 978-0-262-03384-8 523.68 8 输出文件1,打印 输出文件2,均价 使用重载的>> items.txt 使用重载的<< 978-0-321-71411-4, $569.9, 10 978-0-262-03384-8, $523.68, 8 prices.txt 978-0-321-71411-4: $56.99 978-0-262-03384-8: $65.46 关闭文件

Overloading arithmetic operators 返回caller object的引用 参数通常是const引用 Sales_item& operator+= (const Sales_item &item) { assert( this->isbn == item.isbn ); this->revenue += item.revenue; this->units_sold += item.units_sold; return *this; } 实现为类的成员函数

Overloading arithmetic operators The following overloaded operator is also legal (if it really makes some sense). 返回caller object的引用 Sales_item& operator+= (unsigned int n) { assert( this->units_sold != 0 ); this->revenue += this->avg_price( ) * n; this->units_sold += n; return *this; } 实现为类的成员函数

Overloading arithmetic operators 返回一个新的object 参数应当是const引用 Sales_item operator+ (const Sales_item &item1, const Sales_item &item2) { assert( item1.isbn == item2.isbn ); Sales_item result; result.isbn = item1.isbn; result.revenue = item1.revenue + item2.revenue; result.units_sold = item1.units_sold + item2.units_sold; return result; } 通常需要是类的友元 对应的类要允许复制/有良定义的复制 局部变量result以复制的方式返回

Never go counterintuitive Sales_item operator+ (const Sales_item &item1, const Sales_item &item2) { Sales_item result; result.isbn = item1.isbn; result.revenue = max(item1.revenue, item2.revenue); result.units_sold = max(item1.units_sold, item2.units_sold); return result; } DON’T DO THIS.

Overloading the assignment operator 返回caller object的引用 参数应当是const引用 Sales_item& operator= (const Sales_item &item) { this->isbn = item.isbn; this->revenue = item.revenue; this->units_sold = item.units_sold; return *this; } 需要是类的成员函数 [RECALL] Copy constructors.

Non-copyable objects Sometimes there is the case where we want to forbid an object from being copied. class Sales_item { public: Sale_item( ); Sales_item(const Sales_item&) = delete; Sales_item& operator= (const Sales_item&) = delete; }; 必须显式声明/定义一个默认构造函数 声明拷贝构造函数和拷贝赋值操作符为deleted Sales_item item1; Sales_item item2(item1); Sales_item item3 = item1; Sales_item item1; Sales_item item2; ok. 可以定义两个object error. 找不到拷贝构造函数或拷贝赋值操作符

Singletons In software engineering, the singleton pattern is a software design pattern that restricts the instantiation of a class to one object.

static Singleton* getInstance( ) { Tested on macOS High Sierra ver. 10.13.6 with GCC ver. 4.2.1 [Nov 22, 2018] class Singleton { public: static Singleton* getInstance( ) { if (instance == nullptr) instance = new Singleton( ); return instance; } static void destroyInstance( ) { delete instance; } int data; private: Singleton( ): data(2) { } Singleton(const Singleton&) = delete; Singleton& operator= (const Singleton&) = delete; static Singleton *instance; }; Singleton* Singleton::instance(nullptr); 声明构造函数为private,禁任意创建 声明拷贝构造函数和拷贝赋值操作符为deleted,禁复制 用静态变量instance和相应的静态函数管理唯一对象

error. 构造函数为private error. 构造函数为private ok. ok. 指针p和s指向相同的(唯一)对象 Singleton s; error. 构造函数为private Singleton *s = new Singleton( ); error. 构造函数为private Singleton *s = Singleton::getInstance( ); ok. Singleton *p = Singleton::getInstance( ); ok. 指针p和s指向相同的(唯一)对象 p->data = 7; cout << s->data << ”, ” << p->data; 7, 7 Singleton::destroyInstance( ); ok. 销毁(唯一)对象 Tested on macOS High Sierra ver. 10.13.6 with GCC ver. 4.2.1 [Nov 22, 2018]

Overloading relational operators bool operator== (const Sales_item &item1, const Sales_item &item2) { return item1.isbn == item2.isbn && fabs(item1.revenue – item2.revenue) < 1e-7 && item1.units_sold == item2.units_sold; } 可以定义其他的operator==逻辑 bool operator!= (const Sales_item &item1, const Sales_item &item2) { return !(item1 == item2); }

Overloading relational operators bool operator< (const Sales_item &item1, const Sales_item &item2) { return item1.isbn < item2.isbn; } Many STL functions/algorithms require that objects be comparable. vector<Sales_item> items; sort( items.begin( ), items.end( ) ); 要求Sales_item类定义了operator<,否则编译器报错。

Overloading the subscript operator class StrVector { public: StrVector(const string *arr, size_t n) { … } string& operator[ ] (size_t n) { return element[n]; } const string& operator[ ] (size_t n) const { return element[n]; } private: string *elements; }; version 1 version 2 string s[4] = {“hello”, “how”, “are”, “you”}; StrVector sv1(s, 4); sv1[0] = “hi”; const StrVector sv2(s, 4); cout << sv2[3]; Call version 1. Bounds checking? Call version 2.

Overloading member access operators Problems with pointers: ptr2 ptr3 需要记得delete; 需要清楚什么时候delete ptr1 object Sales_item *ptr1 = new Sales_item( ); Sales_item *ptr2 = ptr1; delete ptr1; delete ptr2; ok. The Sales_item object is deleted. run-time error. Pointer being freed was not allocated.

Smart pointers SomeClass *obj; size_t *count; 自定义SmartPointer类,额外使用一个reference counter,记录当前object被多少个smart pointer指向(即初始的smart pointer被复制了多少次) ptr1 ptr2 ptr3 reference counter object 3 SmartPointer(SomeClass*); SmartPointer(const SmartPointer&); ~SmartPointer( ); SmartPointer& operator= (const SmartPointer&); SomeClass& operator* ( ); SomeClass* operator-> ( );

创建一个新的SmartPointer对象,指向输入参数p所指向的SomeClass对象,同时创建计数器,且计数器的值为1 SomeClass *obj; size_t *count; 主要函数1:构造函数 SmartPointer(SomeClass *p): obj(p), count( new size_t(1) ) { } ptr1 ptr2 ptr3 reference counter object 3 创建一个新的SmartPointer对象,指向输入参数p所指向的SomeClass对象,同时创建计数器,且计数器的值为1

将SmartPointer对象sp复制为一个新的SmartPointer对象,计数器加1 SomeClass *obj; size_t *count; 主要函数2:拷贝构造函数 ptr1 ptr2 ptr3 reference counter object 3 SmartPointer(const SmartPointer &sp): obj(sp.obj), count(sp.count) { ++*count; } 将SmartPointer对象sp复制为一个新的SmartPointer对象,计数器加1

主要函数3:析构函数 计数器减1 如果计数器为0,执行实际的delete SomeClass *obj; size_t *count; ~SmartPointer( ) { if (--*count == 0) { delete obj; delete count; } ptr1 ptr2 ptr3 reference counter object 3 计数器减1 如果计数器为0,执行实际的delete

放弃原有的指向,计数器减1,必要时执行实际的delete 主要函数4:拷贝赋值操作符 SomeClass *obj; size_t *count; SmartPointer& operator= (const SmartPointer &sp) { if (this == &sp) return *this; if (--*count == 0) { delete obj; delete count; } obj = sp.obj; count = sp.count; ++*count; return *this; 防止self-assignment 放弃原有的指向,计数器减1,必要时执行实际的delete ptr1 ptr2 ptr3 reference counter object 3 复制sp,计数器加1

使得SmartPointer类的使用看起来与SomeClass类的指针一样。 SomeClass *obj; size_t *count; 主要函数5-6:成员访问操作符 ptr1 ptr2 ptr3 reference counter object 3 SomeClass& operator* ( ) { return *obj; } SomeClass* operator-> ( ) { return obj; } 使得SmartPointer类的使用看起来与SomeClass类的指针一样。

SomeClass *obj; size_t *count; int *data = new int(-29); SmartPointer sp1(data); cout << *sp1 << endl; cout << sp1.get_count() << endl; SmartPointer *sp2 = new SmartPointer(sp1); cout << **sp2 << endl; cout << sp2->get_count() << endl; SmartPointer sp3(*sp2); cout << *sp3 << endl; cout << sp3.get_count() << endl; delete sp2; SomeClass *obj; size_t *count; -29 1 ptr1 ptr2 ptr3 reference counter object 3 -29 2 -29 3 2

Smart pointers Smart pointer和singleton有什么区别? sp1和sp2有什么关系? SomeClass *obj; size_t *count; ptr1 ptr2 ptr3 reference counter object 3 [THINK] Smart pointer和singleton有什么区别? [THINK] int *data = new int(-29); SmartPointer sp1(data); SmartPointer sp2(data); sp1和sp2有什么关系?

Functors Functors (i.e., function objects) are classes that overload the call operator. Functors allow objects of its type to be used as if they were a function. struct absInt { int operator( )(int val) const { return val < 0 ? –val : val; } }; absInt obj; cout << obj(-7) << endl; cout << absInt( )(-7) << endl; 使用名为obj的absInt类对象的operator( ) 使用临时对象的operator( ),临时对象在语句结束后消亡

Functors class averageLessX { public: averageLessX(int n): val(n) { } bool operator( )(int v1, int v2) const { return (v1 + v2) / 2.0 < val; } private: int val; }; averageLessX avg_less_10(10); cout << avg_less_10(4, 16) << endl; cout << averageLessX(10)(4, 16) << endl; 使用名为avg_less_10的对象 使用临时对象averageLessX(10),临时对象在语句结束后消亡

Functors vs pointers to functions [RECALL] (Lecture 5) bool x_less (const Point &a, const Point &b); bool y_less (const Point &a, const Point &b); void mySort ( vector<Point> &points, bool (*p) (const Point &, const Point &) ) { // 用(*p)(a, b)来比较两个点a和b }

Functors vs pointers to functions struct xLess { bool operator( ) (const Point &p1, const Point &p2) const { return p1.x < p2.x; } }; void mySort (vector<Point> &points, const xLess &comp);

Functors vs pointers to functions Next lecture! struct myLess { virtual bool operator( ) (const Point &p1, const Point &p2) const = 0; }; struct xLess: public myLess { virtual bool operator( ) (const Point &p1, const Point &p2) const { return p1.x < p2.x; } }; struct yLess: public myLess { virtual bool operator( ) (const Point &p1, const Point &p2) const { return p1.y < p2.y; } }; void mySort (vector<Point> &points, const myLess &comp);

Next lecture C++ Primer, Chapter 15