• 沒有找到結果。

第六章 簡介運算子超載

N/A
N/A
Protected

Academic year: 2022

Share "第六章 簡介運算子超載"

Copied!
48
0
0

加載中.... (立即查看全文)

全文

(1)

第六章 簡介運算子超載

(Operator Overloading)

6-1 運算子超載的基礎 6-2 超載二元運算子

6-3 超載邏輯與關係運算子 6-4 超載一元運算子

6-5 使用夥伴函數

6-6 細部檢視指定運算子

6-7 超載註標運算子

(2)

6-1 運算子超載的基礎

„

甚麼是運算子超載?

„

讓運算子(符號)有不同的意義

EX: 運算子的預設意義(以 + 與 = 為例) class frac {……} ;

void main() {

int x=5, y =3, z ; z = x + y ; // 使用‘=‘ ‘+’

int a[10], b[10], c[10]; c = a + b ; // 可乎???

frac f1(3,5), f2(2, 5), f3 ;

f3 = f1 + f2 ; // 3/5 + 2/5 = 1, 可乎?

}

可以重新定義+, = 運算子應用 在frac物件上的意義嗎?

可以重新定義+, = 運算子應用 在frac物件上的意義嗎?

(3)

如果沒有運算子超載能力

void main() {

frac f1(3,5), f2(2, 5) , f3 ;

f3.set(f1.add(f2)) ; // 模擬 f3 = f1 + f2 ; if (f1.great_equal(f2)) // f1 >= f2

cout << “ f1 >= f2” ;

cout<<“f3=“; f3.print() ; // cout << “f3=“<<f3 ; }

Æ 也OK? 缺點? 你的看法

(4)

如何超載運算子

„

在類別中建立運算子函數(operator functions)

„

語法

class classname {

……

// overload 運算子 X

return-type operatorX(arg-list) { ……}

}

(5)

運算子的種類

„

二元運算子(Binary Operators)

„ EX: 5 + 3, 5>=3 …

„ 算術運算: +, -, *, /, =, +=, -=,….,

„ 關係運算: >, <, >=, <=…

„ 邏輯運算: &&, ||, &, |, ^

„

一元運算子

„ a++, --b, -c, +d

„

其他

„ [], (), new, delete, ->, ?:

(6)

6-2 超載二元運算子

„

範例一

class coord { int x, y ;

……

} ;

void main() {

coord o1(10,10), o2(5,3), o3 ; o3 = o1 + o2; // o3 Å (15, 13)

o3.print() ; //later, you can use cout << o3 ; }

(7)

超載運算子+, =

class coord { int x, y ;

……

} ;

void main() {

coord o1(10,10), o2(5,3), o3 ;

o3.set(o1.add(o2)); // o3 = o1 + o2 ;

o3.print() ; //later, you can use cout << o3 ; }

(8)

超載operator+, =

class coord { int x, int y;

public:

coord(){}

coord(int a, int b){x=a; y=b;}

coord add(coord c) { coord temp ;

temp.x = this->x + c.x ; temp.y = this->y + c.y ; return temp ;

}

void set(coord c) {

this->x = c.x; this->y=c.y;

}

void print(){cout<<x<<y<<endl;}

} ;

temp <= o1.add(o2) ; temp <= o1.add(o2) ;

o3.set(o1.add(o2)) ; o3.set(o1.add(o2)) ;

o3 <= temp ;

o3 <= temp ;

(9)

超載operator+, =

class coord {

……

coord

operator+(coord c) { //原add()

coord temp ;

temp.x = this->x + c.x ; temp.y = this->y + c.y ; return temp ;

}

void operator=(coord c) { // 原 set() this->x = c.x; this->y=c.y;

} } ;

void main() {

coord o1(10,10), o2(5,3), o3 ; // 原 o3.set(o1.add(o2));

o3.operator=(o1.operator+(o2));

}

void main() {

coord o1(10,10), o2(5,3), o3 ; // 原 o3.set(o1.add(o2));

o3.operator=(o1.operator+(o2));

}

(10)

超載operator+, =

class coord {

……

coord

operator+(coord c) { //原add()

coord temp ;

temp.x = this->x + c.x ; temp.y = this->y + c.y ; return temp ;

}

void operator=(coord c) { // 原 set() this->x = c.x; this->y=c.y;

} } ;

void main() {

coord o1(10,10), o2(5,3), o3 ; // 原 o3.set(o1.add(o2));

// o3.operator=(o1.operator+(o2);

o3 = o1 + o2 ; }

void main() {

coord o1(10,10), o2(5,3), o3 ; // 原 o3.set(o1.add(o2));

// o3.operator=(o1.operator+(o2);

o3 = o1 + o2 ;

}

(11)

牢記運算式的真面目

o3 = o1 + o2 ; o3 = o1 + o2 ;

o3.operator=(o1.operator+(o2)) ; o3.operator=(o1.operator+(o2)) ;

o3 = o1.operator+(o2) ;

o3 = o1.operator+(o2) ;

(12)

回憶如何超載運算子

„

在類別中建立運算子函數(operator functions)

„

語法

class classname {

……

// overload 運算子 X

return-type operatorX(arg-list) { ……}

}

(13)

將超載運算子定義在class外

class coord {

……

coord operator+(coord c) ; void operator=(coord c) ; } ;

coord coord::operator+(coord c) {…….}

void coord::operator=(coord c) {……}

(14)

Yet Another Operator+

class coord {

coord operator+(const coord& ob2) { return coord(x+ob2.x, y+ob2.y) ; }

};

(15)

範例二:

„

承範例一

„

新增 減號‘-’

„

改善 operator=的功能(later)

(16)

範例三:

„

需求

void main() {

coord o1(10,10), o2(5, 3), o3 ; o3 = o1 + 2 ;

}

Q: o3=o1 +2 的真面目?

(17)

範例三(續)

class coord { int x, y ; public:

coord() { x=y=0 ;}

coord(int a) { x = a; y = 0 ;}

coord(int a, int b) {x=a; y=b;}

coord operator+(coord c) { ……}

……

}

void main() {

coord o1(10,10), o2(3,5), o3 ; o3 = o1 + 2 ;

// o3 = o1.operator+(2) ; }

void main() {

coord o1(10,10), o2(3,5), o3 ; o3 = o1 + 2 ;

// o3 = o1.operator+(2) ; }

(18)

範例四: 請使用call by reference

class coord {

……

coord operator+(const coord& c) ; void operator=(const coord& c) ; } ;

coord coord::operator+(const coord& c) {…}

void coord::operator=(const coord& c) {…}

優點? 優點?

(19)

習題

class frac { int u, d ; public:

// 定義+, -, *, /, % = 運算子

} ;

(20)

連加與連等

„

連加, OK?

„

o4 = o1+o2+o3 ;

„

連等, OK? 參考範例二

„

o1=o2=o3;

(21)

習題

„

為frac加入 +=, -=, *=, /=

(22)

6-3 超載邏輯與關係運算子

„

二元運算子(Binary Operators)

„

算術運算: +, -, *, /, =, +=, -=,….,

„

關係運算: >, <, >=, <=, ==…

„

邏輯運算: &&, ||, &, |, ^

(23)

範例一:

class coord { int x, y ; public:

coord() {x = 0 ; y=0 ; }

coord(int i, int j) { x=i; y=j;}

bool

operator==(const coord& ob2) ;

bool

operator&&(const coord& ob2) ; };

void main() { coord o1(10,10); o2(5,3) ;

if (o1 == o2) cout << “o1 == o2” <<endl ;

if (o1 && o2) cout << “as you wish….” <<endl ; }

Q: o1==o2的真面目?

Q: o1==o2的真面目?

(24)

範例一(續)

bool coord::operator==(const coord& ob2) {

return (this->x==ob2.x) && (this->y==ob2.y);

}

(25)

習題:

„

替frac加上==, >, <, >=, <= 運算子

(26)

6-4 超載一元運算子

„

一元運算子

„

++, --, +, -

„

需求:

void main() {

coord o1(10, 10), o2 ;

o2 = ++o1 ; o1.print() ; // 前置++, prefix o2 = o1++ ; o1.print() ;//後置++, postfix }

o1.operator++() o1.operator++()

(27)

範例一: 前置++

class coord { int x, y ; public:

……

coord operator++() {

x++; y++ ; return *this;

} }

Q1:為何不寫 void operator++()?

Q1:為何不寫 void operator++()?

(28)

範例二: 如何分辨prefix與 postfix ++

class coord { int x, y;

public:

coord(){}

coord(int a, int b){x=a; y=b;}

coord& operator++() { // prefix ++

x++; y++ ; return *this;

}

coord operator++(int) {//postfix ++

coord temp = *this ; x++; y++ ;

return temp ; }

}

++o1 ; ++o1 ;

o1++ ;

// 解釋函數內容 o1++ ;

// 解釋函數內容

(29)

範例三: 超載負號

class coord {

coord& operator-() {

x = -x; y =-y; return *this;

}

coord operator-(const coord& c) {

……

} } ;

這樣的operator-對嗎?

try o1 = -o2 ; // o2(10,10) 這樣的operator-對嗎?

try o1 = -o2 ; // o2(10,10)

(30)

習題:

„

class frac

„

加入++, --, -

(31)

6-5 使用夥伴運算子函數

„

源起

„

o3 = o1+o2 ; Æ o3 = o1.operator+(o2) ;

„

o3 = o1+5 ; Æ o3 = o1.operator+(5) ;

„

o3 = 5 + o1 ; Æ o3 = 5.operator+(o1);

?????

使用夥伴函數來定義運算子!

使用夥伴函數來定義運算子!

(32)

範例一: 記起來

#include<iostream.h>

class coord { int x, y ;

……

} ;

coord operator+(coord ob1, coord ob2) {

return coord(ob1.x+ob2.x, ob1.y+ob2.y) ; }

void main() {

coord o1(10,10), o2(5, 3), o3;

o3 = o1 + o2 ; }

// o3 = operator+(o1, o2) ; 參考 operator+(coord, coord) Q1:是否為class coord的成員?

Q2:可否取用x, y ?

參考 operator+(coord, coord) Q1:是否為class coord的成員?

Q2:可否取用x, y ?

friend coord operator+(coord ob1, coord ob2) ;

(33)

範例二: 10+ob2的解決

class coord{

int x, y ; public:

coord(){x=0;y=0;}

coord(int a){x=a;y=a;}

coord(int a, int b){x=a;y=b;}

friend coord operator+(coord ob1, coord ob2);

void print(){cout<<x<<y<<endl;}

} ;coord operator+(coord ob1, coord ob2) { return coord(ob1.x+ob2.x, ob1.y+ob2.y) ; }

void main() { coord o1(10,10), o2(5, 3), o3;

o3 = 10 + o2 ; // It’s OK, why ?}

(34)

範例三: 自己看

„

一元運算符號的負載

„

使用friend functions

(35)

很多個class的operator+

class coord { ……};

class frac {……} ;

coord operator+(coord ob1, coord ob2) ; frac operator+(frac ob1, frac ob2) ;

void main() {

coord o1(10,10), o2(5,3), o3;

o3 = o1 + o2 ; // 呼叫哪一個operator+

frac f1(5,3), f2(2,7), f3;

f3 = f1 + f2 ;

}

(36)

定義二元運算子函數的常態

class frac {

// 將以下之外部函數宣告成朋友函數 } ;

frac operaotr+(const frac& f1, const frac& f2) {…}

frac operaotr-(const frac& f1, const frac& f2) {…}

frac operaotr*(const frac& f1, const frac& f2) {…}

frac operaotr/(const frac& f1, const frac& f2) {…}

bool operaotr==(const frac& f1, const frac& f2) {…}

bool operaotr>(const frac& f1, const frac& f2) {…}

……

Q: operator=需要用此種方式嗎?

Q: operator=需要用此種方式嗎?

(37)

6-6 細部檢查指定運算子

„

operatr=要不要有回傳值?

„

void operaotr=(const coord& ob);

„

o1 = o2 = o3 ; // o1 = (o2=o3) ;

„

o1.operator=(o2.operator=(o3)) ;

那要回傳什麼?

那要回傳什麼?

(38)

operator=的回傳值

class coord {

coord operator=(const coord& ob) { x = ob.x ; y = ob.y ;

return ob ; }

}

(39)

operator=的回傳值

class coord {

coord& operator=(const coord& ob) { x = ob.x ; y = ob.y ;

return ob ; }

}

(40)

operator=的回傳值

class coord {

coord& operator=(const coord& ob) { x = ob.x ; y = ob.y ;

return *this ; }

}

this x

y

….

(41)

operator=的內容

class coord {

coord& operator=(const coord& ob) { x = ob.x ; y = ob.y ;

return *this;

}

} ;

Q1: 不寫operator=會不會怎樣? 如 o1 = o2 ; bit-wise copy

Q2: 那寫這個幹嘛? 當成員中有pointer時

(42)

範例一

class strtype {

char *p; int len ;

……

} ;

strtype& strtype::operator=(const strtype&ob){

if (&ob == this) return ; // what means?

if (len < ob.len) { delete[] p; p = new char[ob.len+1] ;}

len = ob.len ; strcpy(p, ob.p) ; return *this ;

}

與copy constructor幾乎相同!

與copy constructor幾乎相同!

(43)

6-7 超載註標運算子

„

需求

class SafeArray { int a[50] ;

……

} ;

void main() { SafeArray s ;

cout << s.get(10) ; // cout << s.a[10] ; s.insert(10, 77) ; // s.a[10] = 77 ;

… }

但我可否使用:

cout << s[10];

s[10] = 77 ; 但我可否使用:

cout << s[10];

s[10] = 77 ;

(44)

operator[]

SafeArray s ;

cout << s[10] ;

// cout << s.operator[](10) ; s[10] = 77 ;

// s.operator[](10) = 77 ;

奇怪, 怎麼會有寫在等號右邊的函數?

奇怪, 怎麼會有寫在等號右邊的函數?

(45)

可寫在等號右邊的函數

int buffer ;

int& get_buffer() ; void main() {

get_buffer() = 10 ;

cout << get_buffer() <<endl ; }

int& get_buffer() { return buffer ;}

(46)

可寫在等號右邊的函數

const int SIZE = 20 ; int a[SIZE] ;

int& getElement(int index) { return a[index] ; } void main() {

getElement(5) = 100 ; // a[5] = 100 ; cout << getElement(5) <<endl ;

}

(47)

安全的陣列

class SafeArray { int a[20] ; public:

int& operator[](int index) { if(index<0 || index >19)

{cout<<“out of boundary”<<endl; exit(1);

}

else {return a[index];}

// DIY, 檢查index的範圍 }

}

void main() { SafeArray sa;

sa[5] = 10 ; cout << sa[5] ; }

EX:

void main() {

SafeArray sa(20) ;

……

} EX:

void main() {

SafeArray sa(20) ;

……

}

(48)

class Frac完成了沒?

參考文獻

相關文件

第五章 多項式.

•至最近連續居留港澳或 海外期間之計算,係以 本簡章申請時間截止日 為計算基準日往前回溯 推算6年或8年。但計算 至西元2015年8月31

以下透過 透過 透過 透過五年級 五年級 五年級 五年級「 「 「 「中華大地任我行 中華大地任我行 中華大地任我行 中華大地任我行」 」 」 」為例 為例 為例作 為例 作 作說明 作 說明 說明

於民國 99 年 12 月 28 日訂定「能源政策」 ,因應 ISO 50001 能源管 理系統外部查核委員意見,於民國 101 年 1 月 10 日 100 學年度第

[r]

Bìyè hòu, Chén Xiǎofēng céng sìchù xúnzhǎo gōngzuò, què wèinéng rúyuàn, yīncǐ.. gǎnjué

開課前 課程第㇐年 首學年末 課程第二年 次學年末.

4.1 多因子變異數分析 多因子變異數分析 多因子變異數分析 多因子變異數分析與線性迴歸 與線性迴歸 與線性迴歸 與線性迴歸 4.1.1 統計軟體 統計軟體 統計軟體 統計軟體 SPSS 簡介 簡介