Lập trình hướng đối tượng với C++ - Chương 4: Định nghĩa toán tử trên lớp

Ngôn ngữ C++

 Định nghĩa toán tử trên lớp

-160-

-170-

-109-

 

1. Giới thiệu chung 109

2. Ví dụ trên lớp số phức 110

2.1 Hàm toán tử là hàm thành phần 110

2.2 Hàm toán tử là hàm bạn 112

3. Khả năng và giới hạn của định nghĩa chồng toán tử 122

Phần lớn toán tử trong C++ đều có thể định nghĩa chồng 122

Trường hợp các toán tử ++ và -- 123

Lựa chọn giữa hàm thành phần và hàm bạn 124

4. Chiến lược sử dụng hàm toán tử 124

Các phép toán một ngôi 124

Các phép toán hai ngôi 124

Các phép gán 124

Toán tử truy nhập thành phần “->” 125

Toán tử truy nhập thành phần theo chỉ số 125

Toán tử gọi hàm 125

5. Một số ví dụ tiêu biểu 125

5.1 Định nghĩa chồng phép gán “ =” 125

5.2 Định nghĩa chồng phép “[]" 130

5.3 Định nghĩa chồng << và >> 133

5.4 Định nghĩa chồng các toán tử new và delete 135

5.5 Phép nhân ma trận véc tơ 137

6. Chuyển đổi kiểu 142

6.1 Hàm toán tử chuyển kiểu ép buộc 143

6.1.1 Hàm toán tử chuyển kiểu trong lời gọi hàm 145

6.1.2 Hàm toán tử chuyển kiểu trong biểu thức 147

6.2 Hàm toán tử chuyển đổi kiểu cơ sở sang kiểu lớp 148

6.2.1 Hàm thiết lập trong các chuyển đổi kiểu liên tiếp 150

6.2.2 Lựa chọn giữa hàm thiết lập và phép toán gán 150

6.2.3 Sử dụng hàm thiết lập để mở rộng ý nghĩa một phép toán 152

6.3 Chuyển đổi kiểu từ lớp này sang một lớp khác 154

6.3.1 Hàm toán tử chuyển kiểu bắt buộc 154

6.3.2 Hàm thiết lập dùng làm hàm toán tử 156

7. Tóm tắt 157

7.1 Ghi nhớ 157

7.2 Các lỗi thường gặp 158

7.3 Một số thói quen lập trình tốt 158

8. Bài tập 158

 

 

 

doc62 trang | Chuyên mục: C/C++ | Chia sẻ: dkS00TYs | Lượt xem: 2871 | Lượt tải: 0download
Tóm tắt nội dung Lập trình hướng đối tượng với C++ - Chương 4: Định nghĩa toán tử trên lớp, để xem tài liệu hoàn chỉnh bạn click vào nút "TẢI VỀ" ở trên
"Ham thiet lap \n";
 real = r; image = i;
 }
 complex(complex &b) {
 cout<<"Ham thiet lap sao chep lai "<<&b<<" Sang "<<this<<endl;
 real = b.real; image = b.image;
 }
 };
void fct(complex p) {
 cout<<"Goi fct \n";
 }
void main() {
 clrscr();
 complex a(3,4);
 a = complex(12);
 a = 12;
 fct(4);
 getch();
 }
Ham thiet lap
Ham thiet lap dong vai tro cua ham toan tu chuyen kieu ngam dinh
Ham thiet lap dong vai tro cua ham toan tu chuyen kieu ngam dinh
Ham thiet lap dong vai tro cua ham toan tu chuyen kieu ngam dinh
Goi fct
Hàm thiết lập trong các chuyển đổi kiểu liên tiếp
Trong lớp số phức complex hàm thiết lập với một tham số cho phép thực hiện chuyển đổi float -->complex đồng thời cả chuyển đổi ngầm định
int --> float. tức là nó có thể cho phép một chuỗi các chuyển đổi:
int --> float -->complex
Chẳng hạn khi gặp phép gán kiểu như:
a = 2;
Cần chú ý khả năng chuyển đổi này phải dựa trên các quy tắc chuyển đổi thông thường như đã nói ở trên. 
Lựa chọn giữa hàm thiết lập và phép toán gán
Với chỉ thị gán:
a=12;
trong chương trình complex9.cpp không có định nghĩa toán tử gán một số nguyên cho một đối tượng complex. Giả sử có một toán tử gán như vậy thì có thể sẽ xảy ra xung đột giữa:
chuyển đổi float-->complex bởi hàm thiết lập và phép gán complex-->complex.
sử dụng trực tiếp toán tử gán float-->complex.
Để giải quyết vấn đề này ta tuân theo quy tắc : “Các chuyển đổi do người sử dụng định nghĩa chỉ được thực hiện khi cần thiết”, nghĩa là với chỉ thị gán:
a = 12;
nếu như trong lớp complex có định nghĩa toán tử gán, nó sẽ được ưu tiên thực hiện. Chương trình sau đây minh hoạ nhận xét này:
Ví dụ 4.15
/*complex10.cpp*/
#include 
#include 
class complex {
 float real, image;
 public:
 complex(float r) {
 cout<<"Ham thiet lap dong vai tro cua ham toan tu chuyen kieu ngam dinh\n";
 real = r; image = 0;
 }
 complex(float r, float i ) {
 cout<<"Ham thiet lap \n";
 real = r; image = i;
 }
 complex & operator=(complex &p) {
 real = p.real;image = p.image;
 coutcomplex tu "<<&p<<" sang "<<this<<endl;
 return *this;
 }
 complex & operator=(float n) {
 real = n;image = 0;
 coutcomplex "<<endl;
 return *this;
 }
 };
void main() {
 clrscr();
 complex a(3,4);
 a = 12;
 getch();
 }
Ham thiet lap
gan float -->complex
Sử dụng hàm thiết lập để mở rộng ý nghĩa một phép toán
Ta xét lớp complex và hàm thiết lập một tham số của lớp được bổ sung thêm một hàm toán tử dưới dạng hàm bạn (trường hợp này không nên sử dụng hàm toán tử thành phần). Với các điều kiện này, khi a là một đối tượng kiểu complex, biểu thức kiểu như:
a + 3
sẽ có ý nghĩa. Thực vậy trong trường hợp này chương trình dịch sẽ thực hiện các thao tác sau:
chuyển đổi từ số thực 3 sang số phức complex.
cộng giữa đối tượng nhận được với a bằng cách gọi hàm toán tử operator+.
Kết quả sẽ là một đối tượng kiểu complex. Nói cách khác, biểu thức a + 3 tương đương với
operator+(a, point(3)).
Tương tự, biểu thức 
5 + a
sẽ tương đương với:
operator+(point(5),a).
Tuy nhiên trường hợp sau sẽ không còn đúng khi operator+ là hàm toán tử thành phần. Sau đây là một chương trình minh hoạ các khả năng mà chúng ta vừa đề cập.
Ví dụ 4.16
/*complex11.cpp*/
#include 
#include 
#include 
class complex {
 float real, image;
 public:
 complex(float r) {
 cout<<"Ham thiet lap dong vai tro cua ham toan tu chuyen kieu ngam dinh\n";
 real = r; image = 0;
 }
 complex(float r, float i ) {
 cout<<"Ham thiet lap 2 tham so\n";
 real = r; image = i;
 }
 void display() {
 cout=0?"+j*":"-j*")<<fabs(image)<<endl;
 }
 friend complex operator+(complex , complex);
 };
complex operator+(complex a, complex b) {
 complex c(0,0);
 c.real = a.real + b.real;
 c.image = a.image + b.image;
 return c;
 }
void main() {
 clrscr();
 complex a(3,4),b(9,4);
 a = b + 5;a.display();
 a = 2 + b;a.display();
 getch();
 }
Ham thiet lap 2 tham so
Ham thiet lap 2 tham so
Ham thiet lap dong vai tro cua ham toan tu chuyen kieu ngam dinh
Ham thiet lap 2 tham so
14+j*4
Ham thiet lap dong vai tro cua ham toan tu chuyen kieu ngam dinh
Ham thiet lap 2 tham so
11+j*4
Nhận xét
Hàm thiết lập làm nhiệm vụ của hàm toán tử chuyển đổi kiểu cơ sở sang kiểu lớp không nhất thiết chỉ có một tham số hình thức. Trong trường hợp hàm thiết lập có nhiều tham số hơn, các tham số tính từ tham số thứ hai phải có giá trị ngầm định.
Chuyển đổi kiểu từ lớp này sang một lớp khác
Khả năng chuyển đổi qua lại giữa kiểu cơ sở và một kiểu lớp có thể được mở rộng cho hai kiểu lớp khác nhau:
Trong lớp A, ta có thể định nghĩa một hàm toán tử để thực hiện chuyển đổi từ kiểu A sang kiểu B (cast operator).
Hàm thiết lập của lớp A chỉ với một tham số kiểu B sẽ thực hiện chuyển đổi kiểu từ B sang A.
Hàm toán tử chuyển kiểu bắt buộc
Ví dụ sau đây minh hoạ khả năng dùng hàm toán tử complex của lớp point cho phép thực hiện chuyển đổi một đối tượng kiểu point thành một đối tượng kiểu complex.
Ví dụ 4.17
/*pointcomplex1.cpp*/
#include 
#include 
#include 
class complex;//khai báo trước lớp complex
class point {
 int x, y;
 public:
 point(int ox = 0, int oy =0) {x = ox; y = oy;}
 operator complex();//chuyển đổi point-->complex
 };
class complex {
 float real, image;
 public:
 complex(float r=0, float i=0 ) {
 real = r; image = i;
 }
 friend point::operator complex();
 void display() {
 cout=0?"+j*":"-j*")<<fabs(image)<<endl;
 }
 };
point::operator complex() {
 complex r(x,y);
 cout<<"Chuyen doi "<<x<<" "<<y
 <<" thanh "<<r.real<<" + "<< r.image<<endl;
 return r;
 }
void main() {
 clrscr();
 point a(2,5); complex c;
 c = (complex) a; c.display();
 point b(9,12);
 c = b; c.display();
 getch();
 }
Chuyen doi 2 5 thanh 2 + 5
2+j*5
Chuyen doi 9 12 thanh 9 + 12
9+j*12
Hàm thiết lập dùng làm hàm toán tử
Chương trình sau đây minh hoạ khả năng dùng hàm thiết lập complex(point) biểu để thực hiện chuyển đổi một đối tượng kiểu point thành một đối tượng kiểu complex.
Ví dụ 4.18
/*pointcomplex2.cpp*/
#include 
#include 
#include 
class point;//khai báo trước lớp complex
class complex {
 float real, image;
 public:
 complex(float r=0, float i=0 ) {
 real = r; image = i;
 }
 complex(point);
 void display() {
 cout=0?"+j*":"-j*")<<fabs(image)<<endl;
 }
 };
class point {
 int x, y;
 public:
 point(int ox = 0, int oy =0) {x = ox; y = oy;}
 friend complex::complex(point); 
 };
complex::complex(point p) {
 real= p.x; image = p.y;
 }
void main() {
 clrscr();
 point a(3,5);
 complex c = a; c.display();
 getch();
 }
3+j*5
Tóm tắt
Ghi nhớ
Toán tử được định nghĩa chồng bằng cách định nghĩa một hàm toán tử. Tên hàm toán tử bao gồm từ khoá operator theo sau là ký hiệu của toán tử được định nghĩa chồng.
Hầu hết các toán tử của C++ đều có thể định nghĩa chồng. Không thể tạo ra các ký hiệu phép toán mới.
Phải đảm bảo các đặc tính nguyên thuỷ của toán tử được định nghĩa chồng, chẳng hạn: độ ưu tiên, trật tự kết hợp, số ngôi .
Không sử dụng tham số có giá trị ngầm định để định nghĩa chồng toán tử.
Các toán tử (), [], ->, = yêu cầu hàm toán tử phải là hàm thành phần của lớp.
Hàm toán tử có thể là hàm thành phần hoặc hàm bạn của lớp.
Khi hàm toán tử là hàm thành phần, toán hạng bên trái luôn là đối tượng thuộc lớp.
Nếu toán hạng bên trái là đối tượng của lớp khác thì hàm toán tử tương ứng phải là hàm bạn.
Chương trình dịch không tự biết cách chuyển kiểu giữa kiểu dữ liệu chuẩn và kiểu dữ liệu tự định nghĩa. Vì vậy người lập trình cần phải mô tả tường minh các chuyển đổi này dưới dạng hàm thiết lập chuyển kiểu hay hàm toán tử chuyển kiểu.
Một hàm toán tử chuyển kiểu thực hiện chuyển đổi từ một đối tượng thuộc lớp sang đối tượng thuộc lớp khác hoặc một đối tượng có kiểu được định nghĩa trước.
Hàm thiết lập chuyển kiểu có một tham số và thực hiện chuyển đổi từ một giá trị sang đối tượng kiểu lớp.
Toán tử gán là toán tử hay được định nghĩa chồng nhất, đặc biệt khi lớp có các thành phần dữ liệu động.
Để định nghĩa chồng toán tử tăng, giảm một ngôi, phải phân biệt hai hàm toán tử tương ứng cho dạng tiền tố và dạng hậu tố.
Các lỗi thường gặp
Tạo một toán tử mới.
Thay đổi định nghĩa của các toán tử trên các kiểu được định nghĩa trước.
Cho rằng việc định nghĩa chồng một toán tử sẽ tự đông kéo theo định nghĩa chồng của các toán tử liên quan.
Quên định nghĩa chồng toán tử gán và hàm thiết lập sao chép cho các lớp có các thành phần dữ liệu động.
Một số thói quen lập trình tốt
Sử dụng toán tử định nghĩa chồng khi điều đó làm cho chương trình trong sáng hơn.
Tránh lạm dụng định nghĩa chồng toán tử vì điều đó dẫn đến khó kiểm soát chương trình.
Chú ý đến các tính chất nguyên thuỷ của toán tử được định nghĩa chồng.
Hàm thiết lập, toán tử gán, hàm thiết lập sao chép của một lớp thường đi cùng nhau.
Bài tập
Bài tập 4.1. 
Bổ sung thêm một số toán tử trên lớp số phức complex.
Định nghĩa hai phép toán vào ra trên lớp vector.
Bài tập 4.2. 
Một ma trận được hiểu là một vector mà mỗi thành phần của nó lại là một vector. Theo tinh thần đó hãy định nghĩa lớp matrix dựa trên vector. Tìm cách để cho chương trình dịch hiểu được phép truy nhập
m[i][j] trong đó m là một đối tượng thuộc lớp matrix.
Bài tập 4.3. 
Định nghĩa các phép nhân, cộng, trừ trên các ma trận vuông.
Bài tập 4.4. 
Dựa trên định nghĩa của lớp complex , lớp vector và lớp matrix để xây dựng chương trình mô phỏng các thao tác trên ma trận và vector phức.
Bài tập 4.5. 
Thay thế hàm thành phần tick() trong lớp date_time bài tập 3.10 bởi hàm toán tử tương ứng với phép toán ++.
Bài tập 4.6. 
Tạo lớp phân số PS với các khả năng sau:
Tạo một hàm thiết lập với mẫu số dương, ở dạng tối giản hoặc rút gọn về dạng tối giản.
Định nghĩa chồng các toán tử cộng, trừ, nhân, chia cho lớp này.
Định nghĩa chồng các toán tử quan hệ trên lớp số phức.

File đính kèm:

  • docLập trình hướng đối tượng với C++ - Chương 4 Định nghĩa toán tử trên lớp.doc