CÁC HÀM TOÁN TỬ CÓ THỂ LÀ CÁC THÀNH VIÊN CỦA LỚP HOẶC

Một phần của tài liệu Giáo trình lập trình hướng đối tượng (Trang 77 - 80)

CHƯƠNG 4: ĐA NĂNG HÓA TOÁN TỬ

IV. CÁC HÀM TOÁN TỬ CÓ THỂ LÀ CÁC THÀNH VIÊN CỦA LỚP HOẶC

Các hàm toán tử có thể là các hàm thành viên hoặc hàm không thành viên; hàm không thành viên thường là các hàm friend. Các hàm thành viên sử dụng ngầm con trỏ this để chứa một trong các tham số đối tượng lớp của chúng. Tham số lớp đó phải được liệt kê một cách tường minh trong lời gọi hàm không thành viên.

Khi đa năng hóa (), [], -> hoặc =, hàm đa năng hóa toán tử phải được khai báo như một thành viên lớp.

Đối với các toán tử khác, các hàm đa năng hóa toán tử có thể là các hàm không thành viên (thường là các hàm friend).

Liệu có phải một hàm toán tử được cài đặt như một hàm thành viên hoặc như hàm không thành viên, toán tử vẫn còn được sử dụng cùng cách trong biểu thức. Như vậy cách là cách cài đặt nào tốt nhất?

Khi một hàm toán tử được cài đặt như một hàm thành viên, toán hạng cực trái phải là một đối tượng lớp của toán tử. Nếu toán hạng bên trái phải là một đối tượng của lớp khác hoặc một kiểu có sẵn thì hàm toán tử này phải được cài đặt như hàm không thành viên. Một hàm toán tử cài đặt như hàm không thành viêân cần là một friend nếu hàm phải truy cập đến các thành viên private hoặc protected.

Các hàm thành viên chỉ được gọi khi toán hạng trái của một toán tử hai ngôi là một đối tượng cụ thể của lớp đó, hoặc khi toán hạng đơn của một toán tử một ngôi là một đối tượng của lớp đó.

. .* :: ?: sizeof

78

Ví dụ 4.1: Chúng ta xây dựng lớp số phức với tên lớp là Complex và đa năng hóa toán tử + trên lớp này.

1: #include <iostream.h>

2:

3: class Complex 4: {

5: private:

6: double Real, Imaginary;

7: public:

8: Complex(double R=0.0,double I=0.0);// Constructor mặc định 9: void Print(); // Hiển thị số phức

10: Complex operator+(Complex Z); // Phép cộng giữa hai số phức 11: Complex operator+(double R); //cộng một số phức với một số thực 12: };

13: 14: Complex::Complex(double R,double I) 15: {

16: Real = R;

17: Imaginary = I;

18: }

19: 20: void Complex::Print() 21: {

22: cout<<'('<<Real<<','<<Imaginary<<')';

23: } 24:

25: Complex Complex::operator + (Complex Z) 26: {

27: Complex Tmp;

28: Tmp.Real = Real + Z.Real;

29: Tmp.Imaginary = Imaginary + Z.Imaginary;

30: return Tmp;

31: }

32: 33: Complex Complex::operator + (double R) 34: {

35: Complex Tmp;

36: Tmp.Real = Real + R;

37: Tmp.Imaginary = Imaginary;

38: return Tmp;

39: } 40:

41: int main() 42: {

43: Complex X,Y(4.3,8.2),Z(3.3,1.1);

44: cout<<"X: ";

45: X.Print();

46: cout<<endl<<"Y: ";

47: Y.Print();

48: cout<<endl<<"Z: ";

49: Z.Print();

50: X = Y + Z;

51: cout<<endl<<endl<<"X = Y + Z:"<<endl;

52: X.Print();

53: cout<<" = ";

54: Y.Print();

55: cout<<" + ";

56: Z.Print();

79

57: X = Y + 3.5;

58: cout<<endl<<endl<<"X = Y + 3.5:"<<endl;

59: X.Print();

60: cout<<" = ";

61: Y.Print();

62: cout<<" + 3.5";

63: return 0;

64: }

Hàm thành viên toán tử operator + () (từ dòng 25 đến 31 và từ dòng 33 đến 39) trả về một đối tượng có kiểu Complex là tổng của hai số phức hoặc tổng của một số phức với một số thực. Chú ý rằng đối tượng tam thời Tmp được dùng bên trong hàm operator + () để giữ kết quả, và đó là đối tượng được trả về.

Chúng ta chạy ví dụ 4.1, kết quả ở hình 4.3

Hình 4.3: Kết quả của ví dụ 4.1

Do đa năng hóa toán tử + trên lớp Complex ở ví dụ 4.1, chúng ta có thể viết:

X = Y + Z;

Câu lệnh này được trình biên dịch hiểu:

X = Y.operator + (Z);

Như vậy, trong biểu thức Y + Z đối tượng bên trái toán tử + (là đối tượng Y) là đối tượng mà qua đó, hàm thành viên toán tử operator + () được gọi. Do đó hàm thành viên toán tử + chỉ nhận một tham số là đối tượng bên phải toán tử và đối tượng bên trái toán tử là đối tượng tạo lời gọi cho hàm toán tử và được truyền bởi con trỏ this.

Hàm operator + () trả về một đối tượng Complex. Do vậy chúng ta có thể viết:

(Y + Z).Print();

để in trên màn hình số phức của đối tượng được trả về. Đối tượng do Y + Z sinh ra như vậy là một đối tượng tạm thời. Nó sẽ không tồn tại khi hàm thành Print() kết thúc.

Hơn nữa khi trả về một đối tượng, toán tử + cho phép một chuỗi phép cộng. Nên chúng ta cũng có thể viết:

X = X + Y + Z;

Tuy nhiên chúng ta không thể nào viết được câu lệnh sau:

X = 3.5 + Y; // Lỗi !!!

Chính vì lý do này chúng ta chọn một hàm không thành viên để đa năng hóa một toán tử để cho phép toán tử được giao hoán. Chú ý rằng hàm không thành viên không cần thiết phải là hàm friend nếu các hàm set và get thích hợp tồn tại trong phần giao diện public, và đặt biệt nhất nếu các hàm set và get là các hàm inline.

80

Để đa năng hóa toán tử << phải có một toán hạng trái của kiểu ostream & (như là cout trong biểu thức cout<<X), vì thế nó phải là hàm không thành viên. Tương tự, đa năng hóa toán tử >> phải có một toán hạng trái của kiểu istream & (như là cin trong biểu thức cin>>X), vì thế vì thế nó cũng phải là hàm không thành viên.

Ngoại trừ đa năng hóa toán tử >> << liên quan đến dòng nhập/xuất dữ liệu chúng ta có hình 4.4 về cách đa năng hóa toán tử như sau:

Biểu thức Hàm thành viên Hàm không thành viên a#b a.operator#(b) operator#(a,b)

#a a.operator() operator#(a) a=b a.operator=(b)

a[b] a.operator[](b) a(b) a.operator()(b) a-> a.operator->()

a++ a.operator++(0) operator++(a,0) a-- a.operator--(0) operator--(a,0)

Hình 4.4: Việc cài đặt các hàm toán tử

Một phần của tài liệu Giáo trình lập trình hướng đối tượng (Trang 77 - 80)

Tải bản đầy đủ (PDF)

(165 trang)