Nguyễn Công Huy – Khoa CNTT&TT 1 TÁI ĐỊNH NGHĨA TÁI ĐỊNH NGHĨA CÁC TÁC TỬ CÁC TÁC TỬ 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 Tái định nghĩa tác tử nhập - xuất Nguyễn Công Huy – Khoa CNTT&TT 2 Giới thiệu Giới thiệu Tại sao cần tái định nghĩa tác tử? class PhanSo { int tu, mau; public: PhanSo(int=0, int=1){…} void InPs() {…} int LonHon (PhanSo x) { return (tu*x.mau>mau*x.tu); } PhanSo Cong(PhanSo x) {…} }; void main() { PhanSo a(4,9), b(3,7); if(b.LonHon(a)) cout<<“PS b lon hon a”; PhanSo c = b.Cong(a); a.InPs(); cout<< “ + ”; b.InPs(); cout<< “ = ”; c.InPs(); } if ( b > a ) Ta cần có cách viết các phép toán theo dạng gần gũi hơn Phan So c = b + a cout << a << “ + ” << b << “ = ” << c; Nguyễn Công Huy – Khoa CNTT&TT 3 Giới thiệu (tt) 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: <Kiểu trả về> operator <tác tử> ( các đối số ) 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 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, … Nguyễn Công Huy – Khoa CNTT&TT 4 Tái định nghĩa bằng hàm độc lập 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() { PhanSo a(2,5); PhanSo b = operator +(a,10); PhanSo c = a + 20 ; PhanSo d = 20 + a ; // Sai } Phải định nghĩa thêm tác tử: PhanSo operator + (int , PhanSo); Nguyễn Công Huy – Khoa CNTT&TT 5 Tái định nghĩa bằng hàm thành viên 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() { PhanSo a(2,5); PhanSo b = a.operator +(10); PhanSo c = a + 20 ; PhanSo d = 20 + a ; // Sai } 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 Nguyễn Công Huy – Khoa CNTT&TT 6 Tái định nghĩa phép gán (dấu =) 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 { float *ds; int soluong , vitri; public : void operator = ( const Stack& s) { soluong = s.soluong; vitri = s.vitri; delete[] ds; ds = new float[soluong]; for(int i=0; i<vitri; i++) ds[i]= s.ds[i]; } }; void main() { Stack s1(100); … Stack s2(20); … s2 = s1; … s1 = s2; } Nguyễn Công Huy – Khoa CNTT&TT 7 Tái định nghĩa phép gán (dấu =) Tá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 đó. class SinhVien { char mssv[9]; char* hoten; int namsinh; float diemtb; public: SinhVien& operator=(const SinhVien& a){ strcpy(mssv,a.mssv); delete[] hoten; hoten = strdup(a.hoten); namsinh = a.namsinh; diemtb = a.diemtb; return *this; } }; Phải copy dữ liệu Xóa vùng nhớ cũ, cấp vùng nhớ mới và copy dữ liệu void main(){ SinhVien a, b, c; a.Nhap(); c = b = a; //phép gán SinhVien d=a; // hxdsc } Nguyễn Công Huy – Khoa CNTT&TT 8 Tái định nghĩa tác tử xuất – nhập 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: 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 : … friend ostream& operator << (ostream& os, PhanSo p); friend istream& operator >> (istream& is, PhanSo& p); }; Nguyễn Công Huy – Khoa CNTT&TT 9 Tái định nghĩa tác tử xuất – nhập Tái định nghĩa tác tử xuất – nhập Ví dụ 1 class Diem { int x, y; public : … friend ostream& operator << (ostream& os, Diem p); friend istream& operator >> (istream& is, Diem& p); }; ostream& operator << (ostream& os, Diem p) { os << “(” << p.x << “,” << p.y <<“)”; return os; } istream& operator >> (istream& is, Diem& p) { cout << “Nhap hoanh do: ”; is >> p.x; cout << “Nhap tung do: ”; is >> p.y; return is; } void main() { Diem a(2,10), b; cout<< “Gia tri diem A la: ” << a <<endl; cout<< “Nhap gia tri cho diem B: ”<<endl; cin>>b; cout<< “Gia tri diem B la: ” << b <<endl; } Nguyễn Công Huy – Khoa CNTT&TT 10 Tái định nghĩa tác tử xuất – nhập Tái định nghĩa tác tử xuất – nhập Ví dụ 2 class SinhVien { char mssv[10], *hoten; float diemtb; public : … friend ostream& operator << (ostream& os, SinhVien s) { os<<s.mssv<<endl; os<<s.hoten<<endl; os<< s.diemtb<<endl; return 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 ptcang; cout<<“Nhap thong tin: ”; cin >> ptcang; cout << “Sinh vien A: ”; cout << ptcang ; ofstream f1(“MyFile.txt”); f1<<ptcang; f1.close(); ifstream f2(“MyFile.txt”); SinhVien a1; f2>>a1; cout << “Trong file: ”; cout <<a1; f2.close(); } #include <fstream.h> . 1 TÁI ĐỊNH NGHĨA TÁI ĐỊNH NGHĨA CÁC TÁC TỬ CÁC TÁC TỬ 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 Tái định nghĩa tác tử. 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: <Kiểu trả về> operator < ;tác tử& gt; ( các đối số. operator < ;tác tử& gt; ( các đối số ) 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 Các tác tử có thể định nghĩa Số học: +, -, *, /, … Tăng giảm: ++,