Chương 7
TÁI ĐỊNH NGHĨA TÁC TỬ
1
Nội dung
• Giới thiệu
• Tái định nghĩa bằng hàm độc lập
• Tái định nghĩa bằng hàm thành viên
• Tái định nghĩa phép gán (dấu =)
• Tái định nghĩa tác tử xuất – nhập
2
Giới thiệu • Tại sao cần tái định nghĩa tác tử?
class PhanSo {
int tu, mau;
Ta cần có cách viết các phép toán theo dạng gần gũi hơn
public:
PhanSo(int=0, int=1){…} void InPs() {…} int LonHon (PhanSo x) {
return (tu*x.mau>mau*x.tu);}
PhanSo Cong(PhanSo x) {…}
};
if ( b > a ) void main() {
PhanSo a(4,9), b(3,7); if(b.LonHon(a)) Phan So c = b + a
cout<<“PS b lon hon a”;
3
PhanSo c = b.Cong(a); a.InPs(); cout<< “ + ”; b.InPs(); cout<< “ = ”; c.InPs(); cout << a << “ + ” << b << “ = ” << c;
}
Giới thiệu (tt)
• Cơ chế
– C++ cho phép ta tái định nghĩa các tác tử (phép
toán).
– Việc tái định nghĩa tác tử thực hiện tương tự như
tái định nghĩa hàm.
– Cú pháp:
– Có 2 cách dùng để tái định nghĩa tác tử:
• Dùng hàm độc lập
• Dùng hàm thành viên
4
Giới thiệu (tt)
• Các tác tử có thể định nghĩa
– Số học: +, -, *, /, … Tăng giảm: ++, --, +=, *=, …
– So sánh: <, >, >=, <=, ==, !=
– Phép gán: =
– <<, >>, [], new, delete, …
5
Tái định nghĩa bằng hàm độc lập • Thông thường nên khai báo hàm độc lập là hàm bạn của lớp để có thể truy cập các thành phần private của lớp.
• Tác tử sau khi định nghĩa không có tính giao hoán.
class PhanSo { int tu,mau;
public: ... friend PhanSo operator + (PhanSo,int);
}; PhanSo operator + (PhanSo x, int n)
{ return PhanSo(x.tu + x.mau*n, x.mau);}
void main() {
6
PhanSo a(2,5); PhanSo b = operator +(a,10); PhanSo c = a + 20 ; PhanSo d = 20 + a ;
}
Tái định nghĩa bằng hàm thành viên • Đối số đầu tiên của tác tử chính là đối tượng đang xét. => Hàm sẽ có số lượng đối số ít hơn so với hàm độc lập.
class PhanSo { int tu,mau;
public: ... PhanSo operator + (int);
}; PhanSo PhanSo::operator + (int n)
{ return PhanSo(tu + mau*n, mau);}
void main() {
7
Không thể định nghĩa thêm tác tử bằng hàm thành viên cho trường hợp này PhanSo a(2,5); PhanSo b = a.operator +(10); PhanSo c = a + 20 ; PhanSo d = 20 + a ; // Sai
}
Tái định nghĩa phép gán (dấu =) • C++ mặc nhiên sẽ có phép gán (dấu = ) bằng cách gán tương
ứng từng thuộc tính giữa 2 đối tượng.
• Khi thành phần dữ liệu có con trỏ => phải định nghĩa “=”. • Phép gán phải định nghĩa bằng hàm thành viên.
class Stack { void main() {
float *ds; int soluong, vitri;
Stack s1(100); … Stack s2(20);
…
public: ... void operator=(const Stack& s){
s2 = s1; … s1 = s2;
}
soluong = s.soluong;
vitri = s.vitri;
delete[] ds;
ds = new float[soluong];
for(int i=0; i 8 ds[i]= s.ds[i]; } }; class SinhVien { void main(){ char mssv[9]; char* hoten;
int public:
...
SinhVien& operator=(const } SinhVien& a){ Xóa vùng nhớ cũ, cấp vùng
nhớ mới và copy dữ liệu 9 }; VD: PhanSo a(2,5); cout << a << endl; • Các phép toán nhập (>>), xuất (<<) phải được định nghĩa theo dạng hàm độc lập và thường khai báo là friend.
• Thao tác với các dòng (stream) xuất/nhập chuẩn như: – Bàn phím, tập tin dùng để đọc, … (istream)
– Màn hình, tập tin dùng để ghi, … (ostream) class PhanSo { int tu, mau; public : 10 }; public : …
friend ostream& operator << (ostream& os, Diem p);
friend istream& operator >> (istream& is, Diem& p); { os << “(” << p.x << “,” << p.y <<“)”; return os; } istream& operator >> (istream& is, Diem& p) { 11 void main() { Diem a(2,10), b;
cout<< “Gia tri diem A la: ” << a < #include 12Tái định nghĩa phép gán (dấu =)
• Phân biệt giữa phép gán và hàm xây dựng sao chép:
– Phép gán: đối tượng đã tồn tại (có vùng nhớ)
– Hàm xây dựng sao chép: đối tượng chưa có
• Trị trả về của phép gán có thể là chính đối tượng đó.
namsinh; float diemtb;
SinhVien a, b, c;
a.Nhap();
c = b = a; //phép gán
SinhVien d=a; // hxdsc
Phải copy dữ liệu
strcpy(mssv,a.mssv);
delete[] hoten;
hoten = strdup(a.hoten);
namsinh = a.namsinh;
diemtb = a.diemtb;
return *this;
}
Tái định nghĩa tác tử xuất – nhập
• Dùng để xuất nhập trực tiếp đối tượng qua cin, cout:
…
friend ostream& operator << (ostream& os, PhanSo p);
friend istream& operator >> (istream& is, PhanSo& p);
Tái định nghĩa tác tử xuất – nhập
• Ví dụ 1
class Diem {
int x, y;
};
ostream& operator << (ostream& os, Diem p)
cout << “Nhap hoanh do: ”; is >> p.x;
cout << “Nhap tung do: ”; is >> p.y;
return is;}
Tái định nghĩa tác tử xuất – nhập
• Ví dụ 2
class SinhVien {
char mssv[10], *hoten;
float diemtb;
public :
ptcang;
…
friend ostream& operator <<
(ostream& os, SinhVien s) {
os<
friend istream& operator >>
(istream& is, SinhVien& s){
is.getline(s.mssv,9);
is.getline(s.hoten,49);
is >> s.diemtb;
return is; }
};
void main() {
SinhVien
cout<<“Nhap thong tin: ”;
cin >> ptcang;
cout << “Sinh vien A: ”;
cout << ptcang ;
ofstream f1(“MyFile.txt”);
f1<