Lập trình hướng đối tượng
Bài 4: Toán tử
Nội dung
Giới thiệu
Lớp complex
Khả năng và giới hạn của viết chồng toán
tử
Chiến lược sử dụng toán tử
Một số thí dụ
Chuyển kiểu
2
Giới thiệu
Lớp Complex
a,b là 2 số phức
a+b, a-b, a*b, a/b ???
Xác định toán tử giống như việc xác định
hàm (gọi là hàm toán tử)
Từ khóa operator và ký hiệu toán tử
3
Khai báo chồng toán tử
Function name
operator+
operatoroperator*
operator/
operator+=
operator!=
Using
Operator +
Operator –
Operator *
Operator /
Operator +=
Different relational operator
Hàm operator:
Hàm
thành phần
Hàm tự do ( phải là hàm bạn bè)
4
Lớp Complex
Hàm toán tử là hàm thành phần
Có
tham số ẩn (con trỏ this)
// complex1.cpp
#include <iostream>
#include <cmath>
class complex{
float real, image;
public:
complex (float r=0, float i=0){
real=r; image=i;
}
5
Complex class
void display(){
cout<
}
// Function operator+ define binary plus operation
complex operator+ (complex b) {
complex c;
c.real=real+b.real;
c.image=image+b.image;
return c;
}
};
6
Complex class
void main(){
complex a(-2,5), b(3,4);
cout<<“2 complex numbers:\n”;
a.display();
b.display();
cout<<“Sum:\n”;
complex c;
c=a+b; //a.operator+(b)
c.display();
getch();
}
2 complex numbers:
-2+5*i
3+4*i
Sum:
1+9*i
7
Complex class – một số nhận xét
a+b giống như a.operator+(b)
operator+ là hàm thành viên public
Gọi a.operator+(b): a là tham số ẩn còn b
là tham số tường minh
Chương trình dịch không thể thực hiện:
3+a (3.operator+(a)). Để giải quyết vấn đề
này, phải sử dụng hàm bạn bè
8
Hàm toán tử là hàm bạn bè
// the same as complex1.cpp
class complex{
//...
// Free function operator+ defines binary operator +
friend complex operator+(float x, complex b);
};
complex operator+(float x, complex b){
cout<<“call operator+(float, complex)\n”;
complex c;
c.real=x+b.real;
c.image=b.image;
return c;
}
9
Complex class
void main(){
complex a(-2,5), b(3,4), c,d;
cout<<“Sum of 2 complex numbers:\n”;
c=a+b; //a.operator+(b)
c.display();
cout<<“Add 3 to real member of complex number:\n”;
d=3+a; //operator+(3,a)
d.display();
getch();
}
Sum of 2 complex numbers :
1+9*i
Add 3 to real member of complex number :
1+5*i
10
Lớp Complex
Toán tử 1 ngôi
void operrator-(){
real=-real;
image=-image;
}
Một số dạng khác:
complex
& operator-()
complex operator+(float, complex&)
11
Khả năng và giới hạn của việc viết toán tử
Tất cả các toán tử trừ: “.”, “::”, “?:” đều có thể
được xác định
Không thể tạo ký hiệu toán tử mới
Operator = và [ ] phải là hàm thành phần
Operator << và << phải là hàm bạn bè
operator++() và operator--() là toán tử tiền tố;
operator++(int) và operator--(int) là toán tử hậu
tố
operator phải duy trì là 1 hay 2 ngôi
Một trong số các toán hạng phải là đối tượng
12
Chiến lược sử dụng toán tử
Các toán tử nên giữ ngữ nghĩa gốc
Overloadable Operators
+
-
*
/
%
^
&
|
~
!
=
<
>
+=
-=
*=
/=
%=
^=
&=
|=
<<
>>
<<=
>>=
==
!=
<=
>=
&&
||
++
--
->*
.
->
[]
()
new
new[]
delete
delete[]
13
Thí dụ
Phép gán operator“=“
Giả sử a,b là 2 đối tượng vector
Biểu thức: a=b; a.operator=(b);
Lưu ý:
Cần
xác định toán tử gán cho các đối tượng
có dữ liệu thành viên động
14
Thí dụ
vector & vector::operator=(vector &b){
cout<<“Call operator=() for ”<
if (this !=&b){
cout<<“Delete dynamic member data ”<
delete [] v;
// create dynamic member data with the size of b
v=new float[n=b.n];
cout<<“Create dynamic member data ”<
for (int i=0; i
}
else cout<<“2 objects are coincide, do nothing.\n”;
return *this;
}
15
Thí dụ
Toán tử chỉ mục operator “[ ]”
float & operator[](int i){
return v[i];
}
Toán tử operator << và >>
class complex{
float real, image;
friend ostream & operator<<(ostream &o, complex &b);
friend istream & operator>>(istream &i, complex &b);
};
ostream & operator<<(ostream &o, complex &b){
o<
return o;
}
16
Thí dụ
istream & operator>>(istream &i, complex &b){
cout<<“Real member:”; i>>b.real;
cout<<“Image member:”; i>>b.image;
return i;
}
operator new
parameter
return
type: size_t (in stddef.h)
void*
operator delete
parameter
return
type: void*
void
17
Chuyển kiểu
Chuyển lớp về dạng built-in
Giải
sử đối tượng “a” là một số phức
a=2+3*i
float x=3+a; // x=5???
Xác định hàm thành phần mới
operator float() {
return real;
}
18
Chuyển kiểu
Chuyển dạng built-in sang lớp
Giả
sử đối tượng “a” là một số phức
a=3 ???
complex e=3;
Xác định hàm mới
complex (float r) {
cout<<“Constructor function is a default type casting function\n”
real=r; image=0;
}
19
Chuyển kiểu
Chuyển 1 đối tượng sang dạng đt khác
class complex;
class point{
float x,y;
public:
operator complex();
};
class complex {
//...
friend point::operator complex();
};
20
Tình huống: Số hữu tỷ
Dạng mới thể hiện tỷ số của 2 số nguyên:
Fraction a( 3, 4 ); // Represents 3/4
Fraction b( 7 ); // Represents 7/1
Phân số nên có hành vi giống các dạng số khác:
Fraction c( 1, 2 );
if( a < b )
c = b - a;
else
c = a - b;
cout << "Value is " << c << "\n";
21
Số hữu tỷ
Có thể hợp nhất với các dạng số khác:
c = a + 3; // Should mean same as addition of 3/1
double x = 2.5 * a; // Should convert fraction to a
double
22
Các phép toán số học trên số phức
a/b + c/d được xác định là (a*d + c*d)/(b*d)
Fraction operator+(const Fraction& left, const Fraction&
right)
{
Fraction result(left.numerator() * right.denominator()
+ right.numerator() * left.denominator(),
left.denominator() * right.denominator());
return result;
}
Các phép toán khác được xác định tương tự
23
Các phép toán số học một ngôi
+ - * & có cả 2 dạng một và hai ngôi
Để viết chồng các toán tử 1 ngôi, giảm số tham số
đi 1.
Thí dụ:
Fraction operator-(const Fraction& value)
{
Fraction result(-value.numerator(),
value.denominator());
return result;
}
Toán tử 1 ngôi khi được xác định như hàm thành
phần sẽ không có tham số
24
Viết chồng các toán tử so sánh
Thí dụ với lớp phân số:
bool operator==(const Fraction& left, const Fraction& right)
{
return left.numerator() * right.denominator()
== right.numerator() * left.denominator();
}
bool operator<(const Fraction& left, const Fraction& right)
{
return left.numerator() * right.denominator()
< right.numerator() * left.denominator();
}
25