1. Trang chủ
  2. » Công Nghệ Thông Tin

Quá tải toán tử

28 1,3K 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 28
Dung lượng 49,15 KB

Nội dung

Bài giảng lập trình hướng đối tượng - Thầy Cường Học viện bưu chính viễn thông TP HCM

Trang 1

Chương 5

Quá tải toán tử

• Quá tải toán tử đối với lớp

• Quá tải toán tử nhị nguyên

• Quá tải toán tử quan hệ & luận lý

• Quá tải toán tử đơn nguyên

• Hàm toán tử friend

• Toán tử gán

Trang 3

I/ Quá tải toán tử (operator overloading)

Quá tải toán tử giống như quá tải hàm Thực chất quá tải toán tử chỉ là một loại quá tải hàm Một toán tử thường được quá tải đối với một lớp

Khi một toán tử được quá tải, toán tử đó không mất ý nghĩa gốc của nó Thêm nữa, toán tử còn có thêm ý nghiã bổ sung đối với lớp mà toán tử được định nghiã

Để quá tải một toán tử, hãy tạo ra một hàm toán tử (operator function) Thông

thường, một hàm toán tử là một thành viên (member) hoặc bạn (friend) của lớp mà toán tử được định nghiã

Cú pháp

return_type class_name::operator#(arg_list)

{

// operation to be performed }

return_type kiểu trả về của một hàm toán tử có thể là bất kỳ,

thường là lớp mà toán tử được định nghiã class_name tên lớp chứa hàm toán tử

# đại diện cho toán tử được quá tải

arg_list danh sách các đối số, thay đổi phụ thuộc vào cách mà hàm toán tử

được thực hiện và kiểu toán tử được quá tải

• Hai hạn chế khi quá tải toán tử :

+ thứ tụ ưu tiên của các toán tử không thay đổi

+ số toán hạng của một toán tử không thay đổi

Hầu hết các toán tử trong C++ có thể được quá tải

Một số toán tử không thể quá tải như : :: , , * , ?

Cũng không thể quá tải toán tử tiền xử lý

Hai toán tử được quá tải ">>" và "<<" , dùng để thực hiện các thao tác nhập/xuất trong C++

• Các hàm toán tử có thể không có các đối số ngầm định

Trang 4

II/ Quá tải toán tử nhị nguyên

Khi một hàm toán tử thành viên quá tải toán tử nhị nguyên, hàm sẽ chỉ có một tham

số Tham số này sẽ nhận đối tượng nằm bên phải toán tử Đối tượng bên trái là đối

tượng tạo ra lời gọi Gọi cho hàm toán tử và được truyền bởi con trỏ this

Các hàm toán tử được viết theo nhiều cách khác nhau

• Quá tải toán tử "+" đối với một lớp

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

void get_xy(int &i, int &j) { i=x; j=y; }

coord operator+(coord ob2);

};

// Overload + relative to coord class

coord coord::operator+(coord ob2)

Trang 5

o3 = o1 + o2; // add two objects - this calls operator+()

@ Vì đối tượng coord được trả về, câu lệnh sau đây cũng hoàn toàn đúng

(o1 + o2).get_xy(x, y);

• Quá tải toán tử "-" , "=" đối với một lớp

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

void get_xy(int &i, int &j) { i=x; j=y; }

coord operator+(coord ob2);

coord operator-(coord ob2);

coord operator=(coord ob2);

};

// Overload + relative to coord class

coord coord::operator+(coord ob2)

{

coord temp;

temp.x = x + ob2.x;

Trang 6

temp.y = y + ob2.y;

return temp;

}

// Overload - relative to coord class

coord coord::operator-(coord ob2)

// Overload = relative to coord

coord coord::operator=(coord ob2)

Trang 7

@ Với hàm toán tử gán

+ toán hạng bên trái (nghiã là đối tượng được gán cho một giá trị)

được thay đổi bởi phép toán

+ hàm operator=() trả về con trỏ this, nghiã là hàm trả về đối tượng

sẽ được gán Do đó câu lệnh sau cũng hoàn toàn đúng :

o3 = o2 = o1;

Có thể quá tải một toán tử đối với một lớp để cho toán hạng bên phải là một đối

tượng có kiểu định sẵn. Toán tử "+" được quá tải để cộng một giá trị nguyên và đối tượng coord

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

void get_xy(int &i, int &j) { i=x; j=y; }

coord operator+(coord ob2); // ob + ob

coord operator+(int i); // ob + int

};

// Overload + relative to coord class

Trang 8

coord coord::operator+(coord ob2)

Trang 9

@ Cần nhớ, khi quá tải một hàm toán tử thành viên để cho một đối tượng có thể

được dùng trong một phép toán có kiểu định sẵn, thì kiểu định sẵn phải ở bên phải

của toán tử Bởi vì chính đối tượng bên trái tạo ra lời gọi cho hàm toán tử

Điều gì xảy ra cho câu lệnh này ?

o3 = 100 + o1; // int + ob

Có thể dùng tham số qui chiếu trong một hàm toán tử

Ví dụ 2.4

// Overload + relative to coord class using references

coord coord::operator+(coord &ob2)

@ Các lý do phải dùng tham số qui chiếu trong hàm toán tử :

+ Sự hiệu quả Do việc truyền điạ chỉ của một đối tượng thường nhanh hơn và cải thiện năng xuất so với truyền các đối tượng như các tham số cho hàm

+ Tránh những rắc rối gây ra khi bản sao một toán hạng bị hủy Tuy nhiên, có thể định nghiã một hàm hủy bản sao để ngăn ngừa vấn đề này trong trường hợp tổng quát

Bài tập II

1 Hãy tạo quá tải toán tử "*" và "/" đối với lớp coord Viết chương trình

Trang 10

2 Tại sao phần dưới đây là cách sử dụng không thích hợp của một toán tử được quá tải

coord coord::operator%(coord ob)

III/ Quá tải các toán tử quan hệ và luận lý

Khi quá tải các toán tử quan hệ và luận lý để chúng hoạt động theo cách truyền thống, sẽ không cần các hàm toán tử trả về một đối tượng của lớp, thay vào đó các

hàm toán tử trả về một số nguyên để chỉ đúng hay sai

• Quá tải các toán tử "==" và "&&"

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

void get_xy(int &i, int &j) { i=x; j=y; }

Trang 11

int operator&&(coord ob2);

};

// Overload the == operator for coord

int coord::operator==(coord ob2)

{

return x==ob2.x && y==ob2.y;

}

// Overload the && operator for coord

int coord::operator&&(coord ob2)

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

if(o1==o2) cout << "o1 same as o2\n";

else cout << "o1 and o2 differ\n";

if(o1==o3) cout << "o1 same as o3\n";

else cout << "o1 and o3 differ\n";

if(o1&&o2) cout << "o1 && o2 is true\n";

else cout << "o1 && o2 is false\n";

if(o1&&o4) cout << "o1 && o4 is true\n";

else cout << "o1 && o4 is false\n";

return 0;

}

Bài tập III

1 Hãy tạo quá tải toán tử "<" và ">" đối với lớp coord Viết chương trình

Trang 12

IV/ Quá tải toán tử đơn nguyên

Quá tải toán tử đơn nguyên tương tự như toán tử nhị nguyên ngoại trừ chỉ có một

toán hạng

Khi quá tải toán tử đơn nguyên bằng cách dùng hàm thành viên, thì hàm không có

tham số Do chỉ có một toán hạng, nên chính toán hạng này tạo ra lời gọi cho hàm toán tử

• Quá tải toán tử tăng "++" đối với lớp

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

void get_xy(int &i, int &j) { i=x; j=y; }

Trang 13

Dạng thứ hai được khai báo như sau

coord coord::operator++(int notused) ;

với notused luôn luôn được truyền giá trị 0

Với dấu trừ "-", vừa là toán tử nhị nguyên lẫn đơn nguyên trong C++ Làm cách

nào có thể quá tải nó sao cho vẫn giữ được cả hai tính chất này đối với lớp do lập trình viên tạo ra ?

Giải pháp : chỉ cần quá tải nó hai lần, một lần như toán tử nhị nguyên và một lần như toán tử đơn nguyên

Trang 14

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

void get_xy(int &i, int &j) { i=x; j=y; }

coord operator-(coord ob2); // binary minus

coord operator-(); // unary minus

};

// Overload - relative to coord class

coord coord::operator-(coord ob2)

Trang 15

V/ Hàm toán tử friend

Có thể quá tải một toán tử đối với lớp bằng cách dùng hàm friend, nên nhớ hàm friend không có con trỏ this

Với các toán tử nhị nguyên, hàm toán tử friend được truyền cả hai toán hạng

Với các toán tử đơn nguyên, hàm toán tử friend được truyền một toán hạng

Không thể dùng hàm friend để quá tải toán tử gán

• Quá tải toán tử "+" bằng cách dùng hàm friend

Trang 16

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

void get_xy(int &i, int &j) { i=x; j=y; }

};

// Overload + using a friend

coord operator+(coord ob1, coord ob2)

{

coord temp;

temp.x = ob1.x + ob2.x;

temp.y = ob1.y + ob2.y;

Trang 17

@ Toán hạng bên trái được truyền cho tham số thứ nhất, toán hạng bên phải được truyền cho tham số thứ hai

• Quá tải một toán tử bằng cách dùng một friend cung cấp đặc điểm quan trọng mà một hàm thành viên không thể có được Với hàm toán tử friend, có thể để cho những đối tượng được sử dụng trong các phép toán có các kiểu định sẵn, ở

đó kiểu định sẵn nằm ở bên trái toán tử

Trong ví dụ 2.3, chương 5, hàm toán tử thành viên được quá tải

coord coord::operator+(int i)

câu lệnh ob1 = ob2 + 100; là đúng

còn câu lệnh ob1 = 100 + ob2; là sai

Với hàm toán tử friend, có thể định nghiã hàm quá tải sao cho toán hạng bên trái là một đối tượng và toán hạng bên phải là kiểu định sẵn Sau đó, quá tải toán tử này lần nữa với toán hạng bên trái là kiểu định sẵn và toán hạng bên phải là một đối tượng

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

void get_xy(int &i, int &j) { i=x; j=y; }

friend coord operator+(coord ob1, int i);

friend coord operator+(int i, coord ob1);

};

Trang 18

// Overload for ob + int

coord operator+(coord ob1, int i)

// Overload for int + ob

coord operator+(int i, coord ob1)

Trang 19

@ Do đó hai câu lệnh này lúc này hoàn toàn đúng

ob1 = ob2 + 100;

ob1 = 100 + ob2;

• Bằng cách truyền toán hạng cho friend như một tham số tham chiếu, những thay đổi xảy ra bên trong hàm friend có ảnh hưởng đến đối tượng tạo ra lời gọi Quá tải toán tử "++" bằng cách dùng hàm friend

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

void get_xy(int &i, int &j) { i=x; j=y; }

friend coord operator++(coord &ob);

};

// Overload ++ using a friend

coord operator++(coord &ob) // use reference parameter

Trang 20

friend Chỉ cần bổ sung tham số nguyên notused khi định nghiã dạng đứng sau

(nghiã là toán tử "++" đứng sau toán hạng)

coord operator++(coord &ob); // prefix ++O

coord operator++(coord &ob, int notused); // postfix O++

ob * int hoặc int * ob

3 Sử dụng friend, hãy quá tải toán tử " " đối với lớp coord Viết chương trình cho cả hai dạng đứng trước và sau

Trang 21

VI/ Toán tử gán

Theo mặc định, khi một toán tử gán được áp dụng cho một đối tượng thì một bản sao từng bit được đặt vào trong đối tượng bên trái

Tuy nhiên, có những trường hợp mà bản sao từng bit chính xác là không cần Xem một số ví dụ trong chương 2, những trường hợp khi một đối tượng sử dụng bộ nhớ Trong những trường hợp này, cần phải có một phép gán đặc biệt

• Quá tải toán tử "=" trong lớp strtype

char *get() { return p; }

strtype &operator=(strtype &ob);

Trang 22

// see if more memory is needed

if(len < ob.len) { // need to allocate more memory

Trang 23

@ Có hai đặc điểm với hàm operator=() trong ví dụ này

+ nó có một tham số tham chiếu

+ nó trả về tham chiếu chứ không phải một đối tượng

Bài tập VI

1 Cho khai báo lớp dưới đây, hãy thêm vào các chi tiết để tạo nên một kiểu mảng

"an toàn" Sau đó, hãy quá tải toán tử gán để cho bộ nhớ được cấp phát của mảng không bị hủy tình cờ

class dynarray {

int *p;

int size;

public:

dynarray(int s); // pass size of array in s

int &put(int i); // return reference to element i

int get(int i); // return value of element i

// create operator=() function

};

Trang 24

Bài tập chương 5

1 Quá tải các toán tử >> và << đối với lớp coord để cho có các kiểu phép toán sau đây :

- khai báo các đối tượng : three_d o1(6,8,10), o2(3,4,5), o3;

- thực hiện các phép toán : o3 = o1 + o2;

o3 = o1 - o2;

++o1 ; o1;

- xuất nội dung x, y, z của các đối tượng trên

3 Thực hiện lại bài tập 2 dưới dạng tham số tham chiếu đối với các hàm toán tử Dùng hàm friend đối với các toán tử tăng và giảm

Trang 25

4 Viết chương trình thực hiện quá tải toán tử + đối với lớp three_d để cho nó nhận các kiểu phép toán sau : ob + double; double + ob;

5 Viết chương trình thực hiện quá tải các toán tử ==, !=, và // đối với lớp three_d

6 Viết chương trình tạo lớp strtype để cho phép các kiểu toán tử sau :

* ghép chuổi bằng cách dùng toán tử +

* gán chuổi bằng cách dùng toán tử =

* so sánh chuổi bằng cách dùng các toán tử > , < và ==

có thể dùng chuổi có độ dài cố định Trong đó :

- một biến chuổi s[80] có dạng private

- hàm tạo không đối số, thực hiện việc khởi tạo chuổi s là NULL

- hàm tạo có một đối số *p, thực hiện việc chép nội dung chuổi p cho s

- hàm char *get() trả về giá trị của chuổi s

7 Hãy bổ sung các hàm toán tử cần thiết vào chương trình sau

* Toán tử quá tải + cộng mỗi phần tử của toán hạng

* Toán tử quá tải - trừ phần tử toán hạng bên trái với mỗi phần tử của toán hạng bên phải

* Toán tử quá tải == trả về giá trị đúng nếu mỗi phần tử của mỗi toán hạng là giống nhau và trả về giá trị sai nếu ngược lại

array operator+(array ob2);

array operator-(array ob2);

int operator==(array ob2);

};

Trang 27

o3 = o1 + o2;

o3.show();

o3 = o1 - o3;

o3.show();

if(o1==o2) cout << "o1 equals o2\n";

else cout << "o1 does not equal o2\n";

if(o1==o3) cout << "o1 equals o3\n";

else cout << "o1 does not equal o3\n";

return 0;

}

8 Thực hiện lại bài tập 7 với quá tải các toán tử bằng cách dùng hàm friend

Ngày đăng: 21/08/2012, 15:34

TỪ KHÓA LIÊN QUAN

w