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:

operator ( 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

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]; }

};

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 { void main(){

char mssv[9]; char* hoten; int

namsinh; float diemtb;

SinhVien a, b, c; a.Nhap(); c = b = a; //phép gán SinhVien d=a; // hxdsc

public: ... SinhVien& operator=(const } SinhVien& a){

Phải copy dữ liệu

Xóa vùng nhớ cũ, cấp vùng nhớ mới và copy dữ liệu

strcpy(mssv,a.mssv); delete[] hoten; hoten = strdup(a.hoten); namsinh = a.namsinh; diemtb = a.diemtb; return *this;

}

9

};

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);

10

};

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;}

11

void main() {

Diem a(2,10), b; cout<< “Gia tri diem A la: ” << a <>b; cout<< “Gia tri diem B la: ” << b <

Tái định nghĩa tác tử xuất – nhập • Ví dụ 2 class SinhVien {

#include

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; }

12

};

void main() { SinhVien cout<<“Nhap thong tin: ”; cin >> ptcang; cout << “Sinh vien A: ”; cout << ptcang ; ofstream f1(“MyFile.txt”); f1<>a1; cout << “Trong file: ”; cout <