Tải bản đầy đủ (.ppt) (49 trang)

Lập trình hướng đối tượng

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (129.24 KB, 49 trang )

Toán tử đa năng



BÀI 4

Lập trình Hướng đối

1


Mục đích bài học



Toán tử đa năng :









Toán
Toán
Toán
Toán
Toán


tử
tử
tử
tử
tử

một ngôi
hai ngôi
số học hai ngôi
gán phức
so sánh

Đa năng với toán tử gán
Copy constructors

Lập trình Hướng đối

2


Mục đích bài học



Hàm chuyển đổi kiểu







Từ kiểu cơ bản thành kiểu do người
dùng định nghĩa và ngược lại.
Giữa các đối tượng thuộc các lớp
khác nhau.

Những toán tử không thể được
định nghĩa lại.
Lập trình Hướng đối

3


Định nghĩa lại toán tử







Ta có thể kết hợp một toán tử với một hàm thành
viên của lớp. Sau đó toán tử này có thể được dùng
để thực hiện các phép toán trên các đối tượng của
lớp.
Các toán tử +, -, *, / chỉ có thể được dùng trong các
biểu thức với các toán hạng có kiểu cơ bản như int,
float.
Định nghĩa lại một toán tử cho phép ta thực hiện
các phép toán như :




if (obj1 > obj2) { ... }
với obj1 và obj2 là các đối tượng của một lớp.

Lập trình Hướng đối

4


Định nghĩa lại toán tử (tiếp)







Ta định nghĩa một hàm thành viên và gán
nó cho toán tử so sánh >.
Bộ biên dịch có thể phân biệt được những
toán tử đã được định nghĩa lại bằng cách
xét kiểu dữ liệu của các toán hạng.
Định nghĩa lại toán tử chính là một hình
thức của tính đa thể.

Lập trình Hướng đối

5



Những điểm cần lưu ý







Không được phép thay đổi những chức năng
cơ bản của một toán tử hoặc thay đổi thứ tự
ưu tiên của chúng đã được định nghĩa sẵn
trong ngôn ngữ.
toán tử ++ và -- chỉ được sử dụng như những
toán tử một ngôi.
Ta có thể định nghĩa lại toán tử + dùng để
nhân 2 đối tượng. Tuy nhiên ta nên tránh điều
này vì nó làm cho chương trình khó hiểu.

Lập trình Hướng đối

6


Lợi ích






Làm cho chương trình dễ hiểu và dễ
truy tìm lỗi.
Xét ví dụ sau :
obj3 = obj1 + obj2;
cú pháp trên rõ ràng và dễ hiểu hơn cú
pháp :
 obj3.addObjects( obj1, obj2);


Lập trình Hướng đối

7


Hàm toán tử



Hàm toán tử chứa các câu lệnh để
thực hiện việc định nghĩa lại một toán
tử. Ta dùng từ khoá operator theo sau
là toán tử cần định nghĩa lại :




kiểu_trả_về operator
op(danh_sách_đối_số);
trong đó op là biểu tượng của toán tử cần

định nghĩa lại như +, -, * ...

Lập trình Hướng đối

8


Toán tử một ngôi



Toán tử một ngôi chỉ có duy nhất một toán hạng :





++ toán tử một ngôi tăng
-- toán tử một ngôi giảm

Các toán tử này có thể được sử dụng theo 2 cách trước
hoặc sau. Xét ví dụ :
class Sample{
private:
int counter;
public:
Sample() {counter = 0;}
void operator ++() {++counter;}
};


Lập trình Hướng đối

9


Toán tử một ngôi (tiếp)

void main() {
Sample obj1;
obj1++; //tăng counter = 1
++obj1; //tăng counter = 2
}


Nếu bộ biên dịch tìm thấy hàm toán tử đã
được định nghĩa lại trong lớp thì câu lệnh
obj1++ được nó dịch thành obj1.operator+
+();

Lập trình Hướng đối

10


Toán tử một ngôi (tiếp)



Tương tự ta có thể định nghĩa hàm toán tử
giảm như sau :




void operator --() {--counter;}
khi đó ta có thể dùng





--obj1;
obj1--;

Trong các trường hợp trên thì hàm toán tử sẽ
được thực hiện trước tiên dù cho toán tử
đứng trước (--obj1) hay đứng sau (obj1--).

Lập trình Hướng đối

11


Toán tử một ngôi (tiếp)





Trường hợp trên không đáp ứng được yêu
cầu khi ta muốn thực hiện cả tăng và gán

trong một biểu thức như obj1 = obj2++;
Sửa lại hàm trên như sau :


Sample Sample :: void operator++() {
Sample temp;
temp.counter = ++counter;
return temp;
}

Lập trình Hướng đối

12


Sử dụng đối tượng tạm không tên



Trong ví dụ trên ta dùng đối tượng tạm temp,
ta có thể sử dụng cách khác là tạo ra một đối
tượng tạm không tên như sau :
class Sample {
private:
int counter;
public:
Sample() {counter = 0;}
Sample(int c) {counter = c;}
Sample operator++();
};


Lập trình Hướng đối

13


Sử dụng đối tượng tạm không tên
(tiếp)

Sample Sample::void operator++(){
++counter;
return Sample(counter);
}


Trong câu lệnh return trên ta dùng
constructor có một đối số để tạo ra một đối
tượng không tên với giá trị khởi tạo là giá trị
counter, sau đó hàm trả về chính đối tượng
này.

Lập trình Hướng đối

14


Sử dụng con trỏ this




Ngoài ra còn có một các nữa để trả về một
đối tượng là dùng con trỏ this.
Sample Sample::void operator++(){
++counter;
return (*this);
}



Trong trường hợp này thì không cần dùng
hàm khởi tạo có một đối số như ở trên.

Lập trình Hướng đối

15


Gia giảm trước và gia giảm sau



Nếu ++ và -- được định nghĩa lại như trên thì
bộ biên dịch sẽ cho cùng một kết quả trong hai
trường hợp sau :





obj2 = obj1++; và

obj2 = ++obj1;

Để phân biệt được trường hợp toán tử đứng sau
(gia giảm sau) ta định nghĩa hàm với 1 đối số


Sample Sample:: void operator++(int){
return Sample(counter++);
đối số giả
}

Lập trình Hướng đối

16


Toán tử hai ngôi


Toán tử hai ngôi có thể được định nghĩa
lại theo hai cách :




Như là hàm thành viên có một đối số, đối số
này chính là toán hạng bên phải của toán tử.
Ví dụ : khi gặp biểu thức obj1 + obj2 bộ biên
dịch gọi hàm operator+(Sample obj2)
Như là hàm bạn có hai đối số.

Ví dụ : operator+(Sample obj1, Sample obj2)

Lập trình Hướng đối

17


Toán tử số học hai ngôi



Có hai toán hạng tham gia thực hiện một tác
vụ.


Sample Sample::operator+(Sample a){
Sample temp;
temp.counter = counter + a.counter;
return temp;

}


Ta có thể thực hiện phép cộng hai đối tượng
như sau :


obj3 = obj1 + obj2;

Lập trình Hướng đối


18


Toán tử số học hai ngôi (tiếp)



Toán tử + có thể truy cập hai đối tượng :






Đối tượng bên trái toán tử, obj1, sẽ gọi hàm toán
tử.
Đối tượng bên phải toán tử, obj2, là đối số của lời
gọi hàm.

Ta cũng có thể thực hiện biểu thức sau :



obj4 = obj3 + obj2 + obj1;
câu lệnh trên là hợp lệ vì hàm toán tử + trả về
một đối tượng thuộc kiểu Sample.

Lập trình Hướng đối


19


Định nghĩa lại toán tử + cho chuỗi

String String::operator+(String ss){
String temp;
strcpy(temp.str, str); //copy vào biến temp
strcat(temp.str, ss.str); //nối hai chuỗi
return temp;
}


Sử dụng như sau :
String s1 = “Welcome ”;
String s2 = “to C++”;
String s3;
s3 = s1 + s2;

Lập trình Hướng đối

20


Toán tử gán phức

void Sample::operator+=(Sample a){
counter += a.counter;
}





Không cần biến tạm vì giá trị được gán cho
chính đối tượng gọi hàm (bên trái toán tử).
Hàm không có giá trị trả về.

Lập trình Hướng đối

21


Toán tử gán phức (tiếp)


Toán tử này hữu dụng trong các biểu thức như




Muốn thực hiện được các phép tính phức tạp
thì hàm cần giá trị trả về.




obj3 = obj1 +=obj2;

Ta định nghĩa lại như sau :





obj1 += obj2;

Sample Sample::operator+=(Sample a)

Với câu lệnh return đuợc viết lại :
return Sample(counter);
trả về một đối tượng không tên.


Lập trình Hướng đối

22


Toán tử so sánh



Toán tử luận lý và so sánh là toán tử hai
ngôi, nó cần hai đối tượng để so sánh. Ta có
thể định nghĩa lại các toán tử so sánh sau :
<, <=, >, >=, ==, !=


int String::operator>(String ss) {
return (strcmp(str, ss.str) > 0);
}


Lập trình Hướng đối

23


Định nghĩa lại toán tử gán




Toán tử gán mặc định chỉ đơn giản sao chép từng byte đối
tượng nguồn sang đối tượng đích.
Xét trường hợp dữ liệu thành viên là con trỏ và được cấp
phát bộ nhớ bằng new :


class String {
private:
char *str;
public:
String (char *s = “”) {
int length = strlen(s);
str = new char[length + 1];
strcpy(str, s);
}

Lập trình Hướng đối

24



Định nghĩa lại toán tử gán (tiếp)
~String() { delete[] str;}
void display() {cout << str;}
};
void main() {
String s1(“Welcome to my world \n”);
String s2;
s2 = s1;
s1.display();
s2.display();
}


Hai đối tượng s1 và s2 được tạo. Hàm khởi tạo cấp
phát bộ nhớ và sao chép chuỗi vào đó.

Lập trình Hướng đối

25


×