Yêu cầu mọi thông tin sao chép từ blog này phải được ghi rõ đầy đủ: Thông tin được sao chép từ "http://www.dangngochoangthanh.blogspot.com".

Cool wallpaper http://www.fancymessage.com

EMOJI KEYBOARD PRO http://emojiselector.com

THƯ VIỆN HÌNH ĐỘNG FLASH ANIMATION: http://flashanimationlibrary.blogspot.ru/

Hệ thống học trực tuyến đang được phát triển và sẽ đưa vào sử dụng vào cuối năm nay. Hãy xem qua một số demo của Học Trực Tuyến.


HỌC TRỰC TUYẾN ĐÃ CUNG CẤP PHIÊN BẢN TRUY CẬP QUA MOBILE http://dangngochoangthanh.blogspot.com/?m=1

XEM KÊNH HỌC TRỰC TUYẾN TRÊN YOUTUBE



Search on This Blog

Saturday, September 11, 2010

Chồng chất toán tử

Trong ngôn ngữ lập trình hướng đối tượng, có nhiều ngôn ngữ hỗ trợ chồng chất toán tử (các ngôn ngữ hỗ trợ bao gồm C++, Delphi 2009, C#,VB.net, … nhưng mức độ hỗ trợ khác nhau; các ngôn ngữ không hỗ trợ bao gồm Java, Python,…). Chồng chất toán tử (operator overloading) là cách thức xây dựng các hàm thành viên mà tên gọi của chúng là các toán tử đã được định nghĩa trước đó (+, -, *, v.v.). C++ là ngôn ngữ hỗ trợ chồng chất toán tử hoàn hảo. Các toán tử sau đây có thể được chồng chất trong C++
Các toán tử được phép chồng chất
+     -     *     /     =     <     >     +=     -=     *=     /=     <<     >>     <<=     >>=     == !=     <=     >=     ++     –     %     &     ^     !     |     ~     &=     ^=     |=     ||     &&
%=     []     ()     ,     ->*     ->     new     delete     new[]     delete[]
Cấu trúc khai báo chồng chất toán tử
type operator toán_tử(tham số){…thân hàm…}

Ví dụ sau đây sẽ minh họa cho việc chồng chất toán tử. Chúng ta sẽ xây dựng một lớp số phức, xây dựng các phép toán cộng hai số phức (phép toán hai ngôi) và phép tăng số phức lên 1 đơn vị thực và 1 đơn vị ảo(phép toán một ngôi) bằng cách sử dụng chồng chất toán tử.
Ví dụ Kết quả
#include using namespace std;
class Complex{
float real;
float img;
public:
Complex(float, float);
Complex operator +(const Complex&);
Complex operator ++(void);
void toString(void);
};
Complex::Complex(float a, float b){
real = a;
img = b;
}
Complex Complex::operator +(const Complex& b){
Complex c(0, 0);
c.real = real + b.real;
c.img = img + b.img;
return c;
}
Complex Complex::operator ++(void){
Complex c(0, 0);
c.real += ++real;
c.img += ++img;
return c;
}
void Complex::toString(void){
cout<<<” + “<<<”*I”<
}
int main(){
Complex a(3, 2);
Complex b(-1, 1);
(a+b).toString();
(++a).toString();
return 0;
}
2 + 3*I 4 + 3*I
Bạn lưu ý rằng, trong phương thức toán tử, số tham số hình thức luôn bằng hạng của toán tử trừ 1. Điều này có nghĩa là với phép toán một ngôi sẽ không có tham số hình thức, với toán tử hai ngôi sẽ có một tham số hình thức. Điều này là dễ hiểu, bởi đã có một tham số mặc định – đó chính là bản thân đối tượng nội tại. Phép toán cộng, sẽ cộng đối tượng nội tại với một đối tượng khác. Phép toán tăng một đơn vị thực, một đơn vị ảo sẽ làm thay đổi giá trị của đơn vị thực và đơn vị ảo của đối tượng nội tại lên 1. Vì các toán tử này trả về kiểu số phức, nên bạn hoàn toàn có thể thực hiện phép toán phức hợp với chúng (tức là một biểu thức có nhiều toán tử loại này thực hiện trên các hạng tử là các số phức).
(a+ ++b+(a+b)).toString();
Bằng việc sử dụng chồng chất toán tử, biểu thức tính toán sẽ trở nên đơn giản hơn. Bạn cũng có thể sử dụng cách gọi a.operator+(b). Hai cách này cho kết quả như nhau. Đối với hàm toán tử + và ++ ở trên, bạn có thể viết ngắn gọn hơn mà không cần khai báo thêm một biến tạm:
Complex Complex::operator +(const Complex& b){ return Complex(real + b.real, img + b.img);
}
Complex Complex::operator ++(void){
return Complex(++real, ++img);
}
Việc thực hiện các toán tử trên các đối tượng cần yêu cầu đối tượng trước đó phải được khởi tạo giá trị. Nghĩa là phải có một hàm tạo cho đối tượng đó. Mặc dù C++ hỗ trợ chồng chất nhiều toán tử, nhưng bạn không nên lạm dụng nó. Bạn nên sử dụng chồng chất toán tử với mục đích đúng đắn (cộng hai số phức thì sử dụng toán tử + mà không phải là toán tử khác, …).
Việc sử dụng chồng chất toán tử như là hàm thành viên áp dụng cho tất cả các toán tử mà C++ hỗ trợ. Trừ các toán tử gán, hợp nhất, () và ->. Các toán tử còn lại cũng áp dụng cho các hàm toàn cục. Hàm toàn cục cũng như hàm thành viên, nhưng nó không thuộc một lớp nào. Việc khai báo hàm toàn cục sẽ được thực hiện như sau
type operator@(A)
Trong đó, @ là kí hiệu toán tử, A là tên lớp.
Ví dụ Kết quả
#include using namespace std;
class Complex{
public:
float real;
float img;
Complex(float, float);
Complex operator -(const Complex&);
void toString(void);
};
Complex::Complex(float a, float b){
real = a;
img = b;
}
void Complex::toString(void){
cout<<<” + “<<<”*I”<
}
Complex operator -(const Complex &a, const Complex &b){
return Complex(a.real – b.real, a.img – b.img);
}
int main(){
Complex a(3, 2);
Complex b(-1, 1);
(a-b).toString();
return 0;
}
4 + 1*I
Giải thích: trong ví dụ này, hàm toán tử – không phải là hàm thành viên của lớp Complex. Do đó, muốn truy cập đến các thuộc tính của nó, bạn phải quy định các thuộc tính này là public hoặc bạn phải tạo thêm các phương thức getter để thu thập dữ liệu. Cũng vì nó không phải là hàm thành viên của lớp Complex, nên số tham số trong phép toán một ngôi là 1, trong phép toán hai ngôi là 2.
Một điều mà bạn cần lưu ý, đối với toán tử IO overloading (toán tử nhập xuất), chúng ta có một số chú ý:
+ Nếu bạn khai báo hàm toán tử là một thành viên của lớp.
Ví dụ Kết quả
#include using namespace std;
class Vector2D{
private:
int x, y;
public:
Vector2D(){
x = 0;
y = 0;
}
Vector2D(int x1, int y1){
x = x1;
y = y1;
}
ostream& operator<<(ostream& os){
os<<”(“<< x <
<”, “<< y <<”)”;
return os;
}
};
int main()
{
Vector2D ab(4, 5);
//ab.operator<<(cout);
ab<<(cout);
return 0;
}
(4, 5)
Giải thích: hàm toán tử << sẽ thực thi việc in giá trị của đối tượng nội tại (vì nó là thành viên của lớp Vector2D). Nó là toán tử đơn hạng, do đó, trong hàm toán tử không có mặt tham số Vector2D. Đối với cách sử dụng này, ta chỉ có thể gọi nó trong hàm main bằng một trong hai cách sau: ab.operator<<(cout) hoặc ab<<(cout). Cả hai cách gọi này đều không trùng khớp với toán tử xuất (hay toán tử chèn dữ liệu). Thông thường, ta sẽ xuất dữ liệu theo chuẩn cout<
+ Nếu bạn khai báo hàm toán tử không phải là thành viên của lớp.
Ví dụ Kết quả
#include using namespace std;
class Vector2D{
private:
int x, y;
public:
Vector2D(){
x = 0;
y = 0;
}
Vector2D(int x1, int y1){
x = x1;
y = y1;
}
friend ostream& operator<<(ostream&, const Vector2D&);
};
ostream& operator<<(ostream& os, const Vector2D& v){
os<<”(“<< v.x 
<<”, “<< v.y <<”)”;
return os;
}
int main()
{
Vector2D ab(4, 5);
cout<
return 0;
}
(4, 5)
Giải thích: trong ví dụ này, hàm toán tử là một hàm bạn của lớp Vector2D. Nó chứa tham số Vector2D bởi nó không phải là thành viên của lớp nội tại. Khi in giá trị, nó sẽ in giá trị của Vector2D này.
Khi sử dụng toán tử nhập dữ liệu >> (hay toán tử trích tách dữ liệu), bạn khai báo hoàn toàn tương tự. Kiểu dữ liệu trả về lúc này là istream& thay vì bạn sử dụng ostream& như trên. Bạn tiến hành nhập dữ liệu cho nên tham số Vector2D trong hàm bạn cũng cần thay đổi – bạn hãy bỏ đi từ khóa const bởi lẽ bạn đang tiến hành nhập dữ liệu cho nó nên không thể quy định truyền giá trị theo tham số hằng.
Ví dụ Kết quả
#include using namespace std;
class Vector2D{
private:
int x, y;
public:
Vector2D(){
this->x = 0;
this->y = 0;
}
Vector2D(int x, int y){
this->x = x;
this->y = y;
}
friend istream& operator >> (istream&, const Vector2D&);
};
ostream& operator >> (istream& is, const Vector2D& v){
os >> v.x >> v.y;
return is;
}
int main()
{
Vector2D ab(4, 5);
cin >>
 ab;
return 0;
}
(4, 5)
Các kiểu dữ liệu ostream& và istream& nằm trong thư viện iostream của namespace std.

No comments:

Post a Comment