Tải bản đầy đủ (.pdf) (19 trang)

CHƯƠNG 4: ĐA NĂNG HOÁ TOÁN TỬ (OPERATOR OVERLOADING) pptx

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (346.3 KB, 19 trang )

1
Khoa Công Nghệ Thông Tin - Đại Học Bách khoa ĐàNẵng
1
ĐA NĂNG HO
ĐA NĂNG HO
Á
Á
TO
TO
Á
Á
N T
N T


CHƯƠNG
CHƯƠNG
4:
4:
(
(
OPERATOR OVERLOADING
OPERATOR OVERLOADING
)
)
Khoa Công Nghệ Thông Tin và Truyền Thông
Đạihọc Bách khoa – Đạihọc ĐàNẵng
Khoa Công Nghệ Thông Tin - Đại Học Bách khoa ĐàNẵng
2
N
N




i
i
dung
dung
 Đanăng hoá hàm.
 Đanăng hoá toán tử.
 Giớihạncủa đanăng hoá toán tử
 Chuyển đổikiểu.
 Đanăng hoá toán tử xuất(<<)–nhập (>>)
 Đanăng hoá toán tử [], toán tử ()
 Khởitạongầm định - Gán ngầm định.
 Đanăng hoá toán tử ++ và
 Đanăng hoá new và delete
2
Khoa Công Nghệ Thông Tin - Đại Học Bách khoa ĐàNẵng
3
Đa
Đa
năng
năng
ho
ho
á
á
h
h
à
à

m
m
 Định nghĩa các hàm cùng tên
 Đốisố phải khác nhau:
class
Time
Time {
//
long GetTime (void); // số giây tính từ nửa đêm
void GetTime (int &hours,
int &minutes,
int &seconds);
};
 Số lượng  Kiểu
 Có thể dùng đốisố mặc định.
void main() {
int h, m, s;
long t = GetTime();
// Gọihàm???
GetTime(h, m, s); // Gọihàm???
}
 Thứ tự
Khoa Công Nghệ Thông Tin - Đại Học Bách khoa ĐàNẵng
4
Đa
Đa
năng
năng
ho
ho

á
á
to
to
á
á
n
n
t
t


 Định nghĩa các phép toán trên đốitượng.
 Các phép toán có thể tái định nghĩa:
,()[]||&&>=<=><!===
>>=<<=
^=|=&=%=/=-=+==
>><<^|&%/*-+
Nhị
hạng
deletenew
->*->() ++&~!*-+
Đơn
hạng
 Các phép toán không thể tái định nghĩa:
*::?:sizeof
3
Khoa Công Nghệ Thông Tin - Đại Học Bách khoa ĐàNẵng
5
Gi

Gi


i
i
h
h


n
n
c
c


a
a
đa
đa
năng
năng
ho
ho
á
á
to
to
á
á
n

n
t
t


 toán tử gọi hàm () - là một toán tử nhiều ngôi.
 Thứ tựưutiêncủamột toán tử không thểđược
thay đổibởi đanăng hóa.
 Tính kếthợpcủamột toán tử không thểđược thay
đổibởi đanăng hóa. Các tham số mặc định không
thể sử dụng vớimột toán tửđanăng hóa.
 Không thể thay đổisố các toán hạng mà một toán
tử yêu cầu.
 Không thể thay đổi ý nghĩacủamột toán tử làm
việctrêncáckiểucósẵn.
 Không thể dùng đốisố mặc định.
Khoa Công Nghệ Thông Tin - Đại Học Bách khoa ĐàNẵng
6
Đa
Đa
năng
năng
ho
ho
á
á
to
to
á
á

n
n
t
t


 Khai báo và định nghĩa toán tử thựcchất không khác với
việc khai báo và định nghĩanghĩamộtloại hàm bấtkỳ
nào khác
 sử dụng tên hàm là "operator@" cho toán tử "@"
 để overload phép "+", ta dùng tên hàm "operator+"
 Số lượng tham số tại khai báo phụ thuộc hai yếutố:
 Toán tử là toán tửđơnhay đôi
 Toán tửđược khai báo là hàm toàn cụchay phương thức
củalớp
aa@bb aa.operator@(bb) hoặc operator@(aa,bb)
@aa aa.operator@( ) hoặc operator@(aa)
aa@ aa.operator@(int) hoặc operator@(aa,int)
Là phương thứccủalớp Là hàm toàn cục
4
Khoa Công Nghệ Thông Tin - Đại Học Bách khoa ĐàNẵng
7
Đa
Đa
năng
năng
ho
ho
á
á

to
to
á
á
n
n
t
t


 Ví dụ: Sử dụng toán tử "+" để cộng hai đốitượng
MyNumber và trả về kếtquả là một MyNumber
 Ta có thể khai báo hàm toàn cụcsau
const MyNumber operator+(const MyNumber& num1,
const MyNumber& num2);
 "x+y" sẽđượchiểu là "operator+(x,y)"
 dùng từ khoá const để đảmbảo các toán hạng gốc không bị
thay đổi
 Hoặc khai báo toán tử dướidạng thành viên của MyNumber:
const MyNumber operator+(const MyNumber& num);
 đốitượng chủ củaphương thức đượchiểulàtoánhạng thứ nhấtcủa
toán tử.
 "x+y" sẽđượchiểu là "x.operator+(y)"
MyNumber x(5);
MyNumber y(10);

z = x + y;
Khoa Công Nghệ Thông Tin - Đại Học Bách khoa ĐàNẵng
8
Đa

Đa
năng
năng
ho
ho
á
á
to
to
á
á
n
n
t
t


(
(
tt
tt
)
)
 Bằng hàm thành viên:
 Khi đanăng hóa (), [], -> hoặc =, hàm đanăng hóa toán tử phải được
khai báo như một thành viên lớp
class
Point
Point {
public:

Point (int x, int y) { Point::x = x; Point::y = y; }
Point operator + (Point &p) { return Point(x + p.x,y + p.y); }
Point operator - (Point &p) { return Point(x - p.x, y - p.y); }
private:
int x, y;
};
void main() {
Point p1(10,20), p2(10,20);
Point p3 = p1 + p2; Point p4 = p1 - p2;
Point p5 = p3.operator + (p4); Point p6 = p3.operator – (p4);
};
Có 1 tham số
(Nếulàtoántử hai ngôi)
5
Khoa Công Nghệ Thông Tin - Đại Học Bách khoa ĐàNẵng
9
Đa
Đa
năng
năng
ho
ho
á
á
to
to
á
á
n
n

t
t


(
(
tt
tt
)
)
 Toán tử là hàm toàn cục
 Quay lạivớivídụ về phép cộng cho MyNumber, ta
có thể khai báo hàm định nghĩa phép cộng tạimức
toàn cục:
const MyNumber operator+(const MyNumber& num1, const MyNumber& num2);
 Khi đó, ta có thểđịnh nghĩa toán tửđónhư sau:
const MyNumber operator+(const MyNumber& num1,const MyNumber& num2) {
MyNumber result(num1.value + num2.value);
return result;
}
 Ởđây có vấn đề….
 Giải pháp: dùng hàm friend
 friend cho phép mộtlớpcấp quyềntruynhậptớicác
phầnnộibộ củalớp đóchomộtsố cấutrúcđược
chọn
Truy nhậpcácthànhviênprivate value
Khoa Công Nghệ Thông Tin - Đại Học Bách khoa ĐàNẵng
10
Đa
Đa

năng
năng
ho
ho
á
á
to
to
á
á
n
n
t
t


(
(
tt
tt
)
)
 Để khai báo một hàm là friend củamộtlớp, ta phải khai báo hàm đó bên trong
khai báo lớpvàđặttừ khoá friend lên đầu khai báo.
 Lưu ý: tuy khai báo của hàm friend được đặt trong khai báo lớpvàhàmđócó
quyềntruynhập ngang vớicácphương thứccủalớp, hàm đó không phải
phương thứccủalớp
 Không cầnthêmsửa đổigìchođịnh nghĩacủa hàm đã được khai báo là
friend.
 Định nghĩatrướccủa phép cộng vẫngiữ nguyên

class MyNumber {
public:
MyNumber(int value = 0);
~MyNumber();

friend const MyNumber operator+(const MyNumber& num1,const MyNumber& num2);

};
const MyNumber operator+(const MyNumber& num1,const MyNumber& num2) {
MyNumber result(num1.value + num2.value);
return result;
}
6
Khoa Công Nghệ Thông Tin - Đại Học Bách khoa ĐàNẵng
11
Đa
Đa
năng
năng
ho
ho
á
á
to
to
á
á
n
n
t

t


(
(
tt
tt
)
)
 Tại sao dùng toán tử toàn cục?
 Đốivớitoántửđược khai báo là phương thứccủalớp,
đốitượng chủ (xác định bởi con trỏ this) luôn được
hiểulàtoánhạng đầu tiên (trái nhất) của phép toán.
 Nếumuốn dùng cách này, ta phải được quyềnbổ sung
phương thứcvàođịnh nghĩacủalớp/kiểucủatoánhạng trái
 Không phải lúc nào cũng có thể overload toán tử bằng
phương thức
 phép cộng giữa MyNumber và int cầncả hai cách
MyNumber + int và int + MyNumber
 cout << obj;
 không thể sửa định nghĩakiểu int hay kiểucủa cout
 lựachọn duy nhất: overload toán tử bằng hàm toàn cục
Khoa Công Nghệ Thông Tin - Đại Học Bách khoa ĐàNẵng
12
Đa
Đa
năng
năng
ho
ho

á
á
to
to
á
á
n
n
t
t


(
(
tt
tt
)
)
 Bằng hàm toàn cục:nếu toán hạng cựctráicủatoántử là đốitượng
thuộclớp khác hoặcthuộckiểudữ liệucósẵn
 thường khai báo friend
class
Point
Point {
public:
Point (int x, int y) { Point::x = x; Point::y = y; }
friend Point operator + (Point &p, Point &q)
{return Point(p.x + q.x,p.y + q.y); }
friend Point operator - (Point &p, Point &q)
{return Point(p.x - q.x,p.y - q.y); }

private:
int x, y;
};
void main() {
Point p1(10,20), p2(10,20);
Point p3 = p1 + p2; Point p4 = p1 - p2;
Point p5 =operator + (p3, p4); Point p6 = operator – (p3, p4);
};
Có 2 tham số
(Nếulàtoántử hai ngôi)
7
Khoa Công Nghệ Thông Tin - Đại Học Bách khoa ĐàNẵng
13
Đa
Đa
năng
năng
ho
ho
á
á
to
to
á
á
n
n
t
t



(
(
tt
tt
)
)
 Cảitiếnlớptậphợp(Set):
#include <iostream.h>
const maxCard = 100;
enum Bool {false, true};
class
Set
Set {
public:
Set(void) { card = 0; }
friend Bool operator & (const int, Set&);// thanh vien ?
friend Bool operator == (Set&, Set&); // bang ?
friend Bool operator != (Set&, Set&); // khong bang ?
friend Set operator * (Set&, Set&); // giao
friend Set operator + (Set&, Set&); // hop
//
void AddElem(const int elem);
void Copy (Set &set);
void Print (void);
private:
int elems[maxCard];
int card;
};
// Định nghĩa các toán tử

……………….
……………….
int main (void)
{ Set s1, s2, s3;
s1.AddElem(10); s1.AddElem(20);
s1.AddElem(30); s1.AddElem(40);
s2.AddElem(30); s2.AddElem(50);
s2.AddElem(10); s2.AddElem(60);
cout << "s1 = "; s1.Print();
cout << "s2 = "; s2.Print();
if (20 & s1) cout << "20 thuoc s1\n";
cout << "s1 giao s2 = "; (s1 * s2).Print();
cout << "s1 hop s2 = "; (s1 + s2).Print();
if (s1 != s2) cout << "s1 /= s2\n";
return 0;
}
Khoa Công Nghệ Thông Tin - Đại Học Bách khoa ĐàNẵng
14
Chuy
Chuy


n
n
ki
ki


u
u

 Muốnthựchiện các phép cộng:
void main() {
Point p1(10,20), p2(30,40), p3, p4, p5;
p3 = p1 + p2;
p4 = p1 + 5; p5 = 5 + p1;
};
Có thểđịnh nghĩa thêm 2 toán tử:
class
Point
Point {
//
friend Point operator + (Point, Point);
friend Point operator + (int, Point);
friend Point operator + (Point, int);
};
8
Khoa Công Nghệ Thông Tin - Đại Học Bách khoa ĐàNẵng
15
Chuy
Chuy


n
n
ki
ki


u
u

(
(
tt
tt
)
)
void main() {
Point p1(10,20), p2(30,40), p3, p4, p5;
p3 = p1 + p2;
p4 = p1 + 5; // tương đương p1 + Point(5)
p5 = 5 + p1; // tương đương Point(5) + p1
}
class
Point
Point {
//
Point (int x) { Point::x = Point::y = x; }
friend Point operator + (Point, Point);
};
Chuyểnkiểu
5 Ù Point(5)
 Chuyển đổikiểu: ngôn ngữđịnh nghĩasẵn.
Định nghĩa phép chuyển đổikiểu
Khoa Công Nghệ Thông Tin - Đại Học Bách khoa ĐàNẵng
16
Chuy
Chuy


n

n
ki
ki


u
u
(
(
tt
tt
)
)
 Một toán tử chuyển đổikiểucóthểđượcsử
dụng để chuyển đổimột đốitượng củamộtlớp
thành đốitượng củamộtlớp khác hoặc thành
một đốitượng củamộtkiểucósẵn.
 Toán tử chuyển đổikiểunhư thế phải là hàm
thành viên không tĩnh và không là hàm friend.
 Prototype của hàm thành viên này có cú pháp:
 operator <data type> ();
9
Khoa Công Nghệ Thông Tin - Đại Học Bách khoa ĐàNẵng
17
Chuy
Chuy


n
n

ki
ki


u
u
(
(
tt
tt
)
)
class Number {
private:
float Data;
public:
Number(float F=0.0) {
Data=F;
}
operator float() {
return Data;
}
operator int() {
return (int)Data;
}
};
int main() {
Number N1(9.7), N2(2.6);
float X=(float)N1; //Gọi operator float()
cout<<X<<endl;

int Y=(int)N2; //Gọi operator int()
cout<<Y<<endl;
return 0;
}
Ví dụ:
Khoa Công Nghệ Thông Tin - Đại Học Bách khoa ĐàNẵng
18
Đa
Đa
năng
năng
ho
ho
á
á
to
to
á
á
n
n
t
t


xu
xu


t

t
<<
<<
 prototype như thế nào? xét ví dụ:
 cout << num; // num là đốitượng thuộclớp MyNumber
 Toán hạng trái cout thuộclớp ostream, không thể sửa
định nghĩalớp này nên ta overload bằng hàm toàn cục
 Tham số thứ nhất : tham chiếutới ostream
 Tham số thứ hai : kiểu MyNumber,
 const (do không có lý do gì để sửa đốitượng đượcin ra)
 giá trị trả về: tham chiếutới ostream
(để thựchiện được cout << num1 << num2;)
 Kếtluận:
ostream& operator<<(ostream& os, const MyNumber& num)
10
Khoa Công Nghệ Thông Tin - Đại Học Bách khoa ĐàNẵng
19
Đa
Đa
năng
năng
ho
ho
á
á
to
to
á
á
n

n
t
t


xu
xu


t
t
<<
<<
 Khaibáotoántửđược overload là friend củalớp
MyNumber
class MyNumber {
public:
MyNumber(int value = 0);
~MyNumber();

friend ostream& operator<<( ostream& os, const MyNumber& num);

};
 Định nghĩa toán tử
ostream& operator<<(ostream& os, const MyNumber& num) {
os << num.value;
// Use version of insertion operator defined for int
return os; // Return a reference to the modified stream
};
Khoa Công Nghệ Thông Tin - Đại Học Bách khoa ĐàNẵng

20
Đa
Đa
năng
năng
ho
ho
á
á
to
to
á
á
n
n
t
t


nh
nh


p
p
>>
>>
 prototype như thế nào? xét ví dụ:
 cin << num; // num là đốitượng thuộclớp MyNumber
 Toán hạng trái cin thuộclớp istream, không thể

sửa định nghĩalớp này nên ta overload bằng
hàm toàn cục
 Tham số thứ nhất : tham chiếutới istream
 Tham số thứ hai : kiểu MyNumber,
 giá trị trả về: tham chiếutới ostream
(để thựchiện được cin >> num1 >> num2;)
 Kếtluận:
istream& operator>>(istream& is, MyNumber& num)
11
Khoa Công Nghệ Thông Tin - Đại Học Bách khoa ĐàNẵng
21
Đa
Đa
năng
năng
ho
ho
á
á
to
to
á
á
n
n
t
t


xu

xu


t
t
>>
>>
 Khaibáotoántửđược overload là friend củalớp
MyNumber
class MyNumber {
public:
MyNumber(int value = 0);
~MyNumber();

friend istream& operator>>( istream& is, MyNumber& num);

};

Định nghĩa toán tử
istream& operator>>(istream& is, MyNumber& num) {
cout<<“Nhap so:”; is >> num.value;
return is;
// Return a reference to the modified stream
};
Khoa Công Nghệ Thông Tin - Đại Học Bách khoa ĐàNẵng
22
Đa
Đa
năng
năng

ho
ho
á
á
to
to
á
á
n
n
t
t


[ ]
[ ]
 Thông thường để xuấtragiátrị của1 phầntử tạivị trí
cho trước trong đốitượng.
 Định nghĩa là hàm thành viên.
 Để hàm toán tử [] có thểđặt ở bên trái của phép gán thì
hàm phảitrả về là một tham chiếu
class
StringVec
StringVec {
public:
StringVec (const int dim);
~StringVec ();
char* operator [] (int);
int add(char* );
// ………

private:
char **elems; // cac phan tu
int dim; // kich thuoc cua vecto
int used; // vi tri hien tai
};
char* StringVec::operator [] (int i) {
if ( i>=0 && i<used) return elems[i];
return “”;
}

void main() {
StringVec sv1(100);
sv1.add(“PTPhi”);sv1.add(“BQThai”);
sv1.add(“LVLam”); sv1.add(“NCHuy”);
cout<< sv1[2]<<endl;
cout<<sv1[0];
}
12
Khoa Công Nghệ Thông Tin - Đại Học Bách khoa ĐàNẵng
23
Đa
Đa
năng
năng
ho
ho
á
á
to
to

á
á
n
n
t
t


()
()
 Định nghĩa là hàm thành viên.
class
Matrix
Matrix {
public:
Matrix (const short rows, const short cols);
~Matrix (void) {delete elems;}
double& operator () (const short row,
const short col);
friend ostream& operator << (ostream&, Matrix&);
friend Matrix operator + (Matrix&, Matrix&);
friend Matrix operator - (Matrix&, Matrix&);
friend Matrix operator * (Matrix&, Matrix&);
private:
const short rows; // số hàng
const short cols; // số cột
double *elems; // các phần tử
};
double& Matrix::operator ()
(const short row, const short col)

{
static double dummy = 0.0;
return (row >= 1 && row <= rows
&& col >= 1 && col <= cols)
? elems[(row - 1)*cols
+ (col - 1)]
: dummy;
}
void main() {
Matrix m(3,2);
m(1,1) = 10; m(1,2) = 20;
m(2,1) = 30; m(2,2) = 40;
m(3,1) = 50; m(3,2) = 60;
cout<<m<<endl;
}
Khoa Công Nghệ Thông Tin - Đại Học Bách khoa ĐàNẵng
24
Kh
Kh


i
i
t
t


o
o
ng

ng


m
m
đ
đ


nh
nh
 Được định nghĩasẵn trong ngôn ngữ:
VD: Point p1(10,20); Point p2 = p1;
 Sẽ gây ra lỗi(kếtquả SAI) khi bên trong đốitượng

th
th
à
à
nh
nh
ph
ph


n
n
d
d



li
li


u
u
l
l
à
à
con
con
tr
tr

ỏ.
VD: Matrix m(5,6); Matrix n = m;
Lỗisẽ xảy ra do
khởitạongầm
bằng cách gán
tương ứng từng
thành phần.
13
Khoa Công Nghệ Thông Tin - Đại Học Bách khoa ĐàNẵng
25
Kh
Kh



i
i
t
t


o
o
ng
ng


m
m
đ
đ


nh
nh
(
(
tt
tt
)
)
Khi lớpcó
th
th
à

à
nh
nh
ph
ph


n
n
d
d


li
li


u
u
con
con
tr
tr

ỏ,
phải định nghĩa hàm
xây
xây
d
d



ng
ng
sao
sao
ch
ch
é
é
p
p
class
Point
Point {
int x, y;
public:
Point (int =0; int =0 );
// Khong can thiet DN
Point (const Point& p) {
x= p.x;
y = p.y;
}
// ………
};
// ……………
class
Matrix
Matrix {
//….

Matrix(const Matrix&);
};
Matrix::Matrix (const Matrix &m)
: rows(m.rows), cols(m.cols)
{
int n = rows * cols;
elems = new double[n]; // cùng kích thước
for (register i = 0; i < n; ++i) // sao chép phầntử
elems[i] = m.elems[i];
}
Khoa Công Nghệ Thông Tin - Đại Học Bách khoa ĐàNẵng
26
G
G
á
á
n
n
ng
ng


m
m
đ
đ


nh
nh

 Được định nghĩasẵn trong ngôn ngữ:
 Gán tương ứng từng thành phần.
 Đúng khi đốitượng không có dữ liệu con trỏ.
VD
: Point p1(10,20); Point p2; p2 = p1;
 Khi thành phầndữ liệucócon trỏ, bắtbuộcphải
định nghĩa phép gán = cho lớp.
class
Matrix
Matrix {
//….
Matrix& operator = (const Matrix &m) {
if (rows == m.rows && cols == m.cols) { // phảikhớp
int n = rows * cols;
for (register i = 0; i < n; ++i) // sao chép các phầntử
elems[i] = m.elems[i];
}
return *this;
}
};
Hàm
thành
viên
14
Khoa Công Nghệ Thông Tin - Đại Học Bách khoa ĐàNẵng
27
Ph
Ph
é
é

p
p
g
g
á
á
n
n
"="
"="
 Một trong những toán tử hay được overload nhất
 Cho phép gán cho đốitượng này mộtgiátrị dựatrênmột đối
tượng khác
 Copy constructor cũng thựchiệnviệctương tự, cho nên, định
nghĩatoántử gán gầnnhư giống hệt định nghĩacủa copy
constructor
 Ta có thể khai báo phép gán cho lớp MyNumber như
sau:
const MyNumber& operator=(const MyNumber& num);
 Phép gán nên luôn luôn trả về một tham chiếutới đốitượng đích
(đốitượng đượcgántrị cho)
 Tham chiếu đượctrả về phảilàconst để tránh trường hợp a bị
thay đổibằng lệnh "(a = b) = c;" (lệnh đó không tương thích với
định nghĩagốccủa phép gán)
Khoa Công Nghệ Thông Tin - Đại Học Bách khoa ĐàNẵng
28
Ph
Ph
é
é

p
p
g
g
á
á
n
n
"="
"="
 Định nghĩatrêncóthể dùng cho phép gán
 Lệnh if dùng để ngănchặncácvấn để có thể nảysinhkhimột
đốitượng được gán cho chính nó (thí dụ khi sử dụng bộ nhớ
động để lưutrữ các thành viên)
 Ngay cả khi gán một đốitượng cho chính nó là an toàn, lệnh if
trên đảmbảo không thựchiện các công việcthừa khi gán
const MyNumber& MyNumber::operator=(const MyNumber& num) {
if (this != &num) {
this->value = num.value;
}
return *this;
}
15
Khoa Công Nghệ Thông Tin - Đại Học Bách khoa ĐàNẵng
29
Ph
Ph
é
é
p

p
g
g
á
á
n
n
"="
"="
 Khi nói về copy constructor, ta đãbiếtrằng C++
luôn cung cấpmột copy constructor mặc định,
nhưng nó chỉ thựchiện sao chép đơngiản(sao
chép nông)
 Đốivới phép gán cũng vậy
 Vậy, ta chỉ cần định nghĩalại phép gán nếu:
 Ta cầnthựchiện phép gán giữacácđốitượng
 Phép gán nông (memberwise assignment) không đủ
dùng vì
 ta cần sao chép sâu - chẳng hạnsử dụng bộ nhớđộng
 Khi sao chép đòi hỏicả tínhtoán-chẳng hạn gán mộtsố
hiệucógiátrị duy nhấthoặctăng sốđếm
Khoa Công Nghệ Thông Tin - Đại Học Bách khoa ĐàNẵng
30
Đa
Đa
năng
năng
ho
ho
á

á
to
to
á
á
n
n
t
t


++ &
++ &


 Toán tử ++ (hoặc toán tử ) có 2 loại:
 Tiềntố: ++n
 Hậutố: n++ (Hàm toán tửởdạng hậutố có thêm đốisố giả
kiểu int)

Phép tăng ++
 giá trị trả về
 tăng trước ++num
 trả về tham chiếu(MyNumber &)
 giá trị trái - lvalue (có thểđược gán trị)
 tăng sau num++
 trả về giá trị (giá trị cũ trướckhităng)
 trả vềđốitượng tạmthờichứagiátrị cũ.
 giá trị phải - rvalue (không thể làm đích của phép gán)
 prototype

 tăng trước: MyNumber& MyNumber::operator++()
 tăng sau: const MyNumber MyNumber::operator++(int)
16
Khoa Công Nghệ Thông Tin - Đại Học Bách khoa ĐàNẵng
31
Đa
Đa
năng
năng
ho
ho
á
á
to
to
á
á
n
n
t
t


++ &
++ &


 Nhớ lạirằng phép tăng trướctăng giá trị trướckhitrả kếtquả, trong
khi phép tăng sau trả lạigiátrị trướckhităng
 Ta định nghĩatừng phiên bảncủa phép tăng như sau:

MyNumber& MyNumber::operator++() { // Prefix
this->value++; // Increment value
return *this; // Return current MyNumber
}
const MyNumber MyNumber::operator++(int) { // Postfix
MyNumber before(this->value); // Create temporary MyNumber
// with current value
this->value++; // Increment value
return before; // Return MyNumber before increment
}
before là một đốitượng địaphương củaphương
thứcvàsẽ chấmdứttồntạikhilờigọi hàm kết thúc
Khi đó, tham chiếutớinótrở thành bấthợplệ
Không thể trả về tham chiếu
Khoa Công Nghệ Thông Tin - Đại Học Bách khoa ĐàNẵng
32
Tham
Tham
s
s


v
v
à
à
ki
ki



u
u
tr
tr


v
v


 Cũng như khi overload các hàm khác, khi
overload mộttoántử, ta cũng có nhiềulựa
chọnvề việctruyền tham số và kiểutrả về
 chỉ có hạnchế rằng ít nhấtmột trong các
tham số phảithuộckiểungười dùng tựđịnh
nghĩa
 Ởđây, ta có mộtsố lời khuyên về các lựa
chọn
17
Khoa Công Nghệ Thông Tin - Đại Học Bách khoa ĐàNẵng
33
Tham
Tham
s
s


v
v
à

à
ki
ki


u
u
tr
tr


v
v


 Các toán hạng:
 Nên sử dụng tham chiếumỗikhicóthể (đặcbiệtlàkhi
làm việcvớicácđốitượng lớn)
 Luônluônsử dụng tham số là hằng tham chiếukhiđối
số sẽ không bị sửa đổi
bool String::operator==(const String &right) const
 Đốivớicáctoántử là phương thức, điều đócónghĩatanên
khai báo toán tử là hằng thành viên nếu toán hạng đầutiên
sẽ không bị sửa đổi
 Phầnlớn các toán tử (tính toán và so sánh) không sửa đổi
các toán hạng củanó, do đótasẽ rất hay dùng đếnhằng
tham chiếu
Khoa Công Nghệ Thông Tin - Đại Học Bách khoa ĐàNẵng
34
Tham

Tham
s
s


v
v
à
à
ki
ki


u
u
tr
tr


v
v


 Giá trị trả về
 khôngcóhạnchế về kiểutrả vềđốivới toán tửđược
overload, nhưng nên cố gắng tuân theo tinh thầncủa
các cài đặtcósẵncủa toán tử
 Ví dụ, các phép so sánh (==, !=…) thường trả về giá trị kiểu
bool, nên các phiên bản overload cũng nên trả về bool
 là tham chiếu(tới đốitượng kếtquả hoặcmột trong

các toán hạng) hay một vùng lưutrữ mới
 Hằng hay không phảihằng
18
Khoa Công Nghệ Thông Tin - Đại Học Bách khoa ĐàNẵng
35
Tham
Tham
s
s


v
v
à
à
ki
ki


u
u
tr
tr


v
v


 Giá trị trả về …

 Các toán tử sinh mộtgiátrị mớicầncókếtquả trả về là
mộtgiátrị (thay vì tham chiếu), và là const (để đảmbảo
kếtquảđókhôngthể bị sửa đổinhư một l-value)
 Hầuhết các phép toán số học đềusinhgiátrị mới
 ta đãthấy, các phép tăng sau, giảm sau tuân theo hướng dẫn
trên
 Các toán tử trả về một tham chiếutới đốitượng ban đầu
(đãbị sửa đổi), chẳng hạn phép gán và phép tăng trước,
nên trả về tham chiếukhôngphảilàhằng
 để kếtquả có thểđượctiếptụcsửa đổitạicácthaotáctiếptheo
const MyNumber MyNumber::operator+(const MyNumber& right) const
MyNumber& MyNumber::operator+=(const MyNumber& right)
Khoa Công Nghệ Thông Tin - Đại Học Bách khoa ĐàNẵng
36
Tham
Tham
s
s


v
v
à
à
ki
ki


u
u

tr
tr


v
v


 Xem lạicáchtađã dùng để trả về kếtquả của
toán tử:
const MyNumber MyNumber::operator+(const MyNumber& num)
{
MyNumber result(this->value + num.value);
return result;
}
 Cách trên không sai, nhưng C++ cung cấpmột
cách hiệuquả hơn
const MyNumber MyNumber::operator+(const MyNumber& num)
{
return MyNumber(this->value + num.value);
}
1. Gọi constructor để tạo
đốitượng result
2. Gọi copy-constructor để tạobảnsao
dành cho giá trị trả về khi hàm thoát
3. Gọi destructor để huỷđối
tượng result
19
Khoa Công Nghệ Thông Tin - Đại Học Bách khoa ĐàNẵng
37

Tham
Tham
s
s


v
v
à
à
ki
ki


u
u
tr
tr


v
v


 Cú pháp củavídụ trướctạomột đốitượng tạmthời
(temporary object)
 Khi trình biên dịch gặp đoạn mã này, nó hiểu đốitượng
đượctạochỉ nhằmmục đích làm giá trị trả về, nên nó tạo
thẳng một đốitượng bên ngoài (để trả về) - bỏ qua việc
tạovàhuỷđốitượng bên trong lờigọi hàm

 Vậy, chỉ có mộtlờigọi duy nhất đến constructor của
MyNumber (không phải copy-constructor) thay vì dãy lời
gọitrước
 Quá trình này đượcgọilàtối ưu hoá giá trị trả về
 Ghi nhớ rằng quá trình này không chỉ áp dụng được đối
với các toán tử. Ta nên sử dụng mỗikhitạomột đối
tượng chỉđểtrả về
return MyNumber(this->value + num.value);
Khoa Công Nghệ Thông Tin - Đại Học Bách khoa ĐàNẵng
38
Đa
Đa
năng
năng
ho
ho
á
á
new & delete
new & delete
 Hàm new và delete mặc định của ngôn ngữ:
 Nếu đốitượng kích thướcnhỏ, có thể sẽ gây ra quá
nhiềukhốinhỏ => chậm.
 Không đáng kể khi đốitượng có kích thướclớn.
=> Toán tử new và delete ít đượctáiđịnh nghĩa.
 Định nghĩa theo dạng hàm thành viên:
class
Point
Point {
public:

//
void* operator new (size_t bytes);
void operator delete (void *ptr, size_t bytes);
private:
int xVal, yVal;
};
void main() {
Point *p = new Point(10,20);
Point *ds = new Point[30];
//………………
delete p;
delete []ds;
}

×