NHP, Khoa CNTT, Trường ĐHHHVN
Chương 2. Đối tượng và lớp
2.1. Định nghĩa đối tượng, lớp.
2.2. Khai báo lớp, đối tượng.
2.3. Cấu tử và hủy tử.
2.4. Thành phần tĩnh, hàm bạn, lớp bạn.
2.5. Định nghĩa chồng toán tử.
NHP, Khoa CNTT, Trường ĐHHHVN
2.1. Định nghĩa đối tượng, lớp.
 Đối tượng (object): là một thực thể tồn tại trong hệ thống. Mỗi
đối tượng xác định bằng 3 yếu tố:
 định danh đối tượng: xác định duy nhất đt trong hệ thống, phân biệt các
đt với nhau
 trạng thái của đt: là các thuộc tính mô tả đt
 hoạt động của đt: là những hành động mà đt có thể thực hiện được.
NHP, Khoa CNTT, Trường ĐHHHVN
2.1. Định nghĩa đối tượng, lớp.
Ví dụ: Bài toán quản lý nhân viên, mỗi nhân viên là một đối tượng.
– Nhân viên tên là Huy, tuổi 28, hệ số lương 3.00; … là một đối tượng,
Kết quả của việc trừu tượng hóa các đối tượng của thế giới thực
thành các đối tượng lập trình là sự kết hợp giữa dữ liệu (thuộc
tính) và các hàm (phương thức).
NHP, Khoa CNTT, Trường ĐHHHVN
2.1. Định nghĩa đối tượng, lớp
 Lớp (class) là một kiểu dữ liệu mới được dùng để định nghĩa
các đối tượng.
 Một lớp có vai trò như một kế hoạch hay một bản mẫu.
 Việc viết hay tạo ra một lớp mới không sinh ra bất cứ một đối
tượng nào trong chương trình.
NHP, Khoa CNTT, Trường ĐHHHVN
2.2. Khai báo lớp, đối tượng
Khai báo lớp
class tên_lớp [: <kiểu thừa kế> lớp_cha]{
private: // Khai báo các thành phần dữ liệu (thuộc tính) riêng
// Khai báo các phương thức (hàm) riêng
protected: // Khai báo các thành phần dữ liệu được bảo vệ
// Khai báo các phương thức được bảo vệ
public: // Khai báo các thành phần dữ liệu chung
// Khai báo các phương thức chung
};
NHP, Khoa CNTT, Trường ĐHHHVN
Khai báo lớp
 class SV{
private:
string ten;
int masv;
float d1, d2, d3;
public:
SV(){ten=“”; masv=0; d1=d2=d3=0.0;}
void nhap();
void xuat();
float tong(){return d1+d2+d3;}
 };
void SV::nhap(){
cout<<“Nhap ten sv: ”;
cin>>ten;
cout<<“Nhap ma sv: ”;
cin>>masv;
cout<<“Nhap diem: ”;
cin>>d1>>d2>>d3;
}
void SV::xuat(){
cout<<“Ho ten ”<<ten<<endl;
cout<<“Ma sv:
”<<masv<<endl;
cout<<“D mon 1: ”<<d1<<endl;
cout<<“D mon 2: ”<<d2<<endl;
cout<<“D mon 3: ”<<d3<<endl;
cout<<“Tong diem:
”<<tong()<<endl;
}
NHP, Khoa CNTT, Trường ĐHHHVN
Khai báo đối tượng
 Giống như khai báo biến thông thường
 Tên_lớp tên_đối_tượng;
 Ví dụ:
 SV a;
 SV b[10];
 SV *p;
 …
Truy cập:
 tên_đối_tượng.tên_pt/tên_tp
 tên_đối_tượng->tên_pt/tên_tp //với con trỏ
a.ten
a.nhap()
a.tong()
p->xuat()
p->ns
…
NHP, Khoa CNTT, Trường ĐHHHVN
Các thành phần trong lớp
 Các từ khóa private, protected, public quy định phạm vi sử dụng
của các tp dữ liệu hoặc pt.
từ khóa trong lớp ngoài lớp bạn bè thừa kế
pri x x
pro x x x
pub x x x x
NHP, Khoa CNTT, Trường ĐHHHVN
Con trỏ this
 Tất cả các phương thức hoặc tp dữ liệu phải được gọi thông
qua đối tượng nào đó,
 Con trỏ this tham chiếu đến đối tượng đang gọi hàm thành
phần,
 Con trỏ this trong C++ là một từ khóa đề cập đến thể hiện hiện
tại của lớp,
NHP, Khoa CNTT, Trường ĐHHHVN
Con trỏ this
class Employee {
private:
int id;
string name;
float salary;
public:
Employee(int id, string name, float salary) {
this->id = id;
this->name = name;
this->salary = salary;
}
void display() {
cout << this->id << " " << this->name << " " << this->salary << endl;
}
};
int main() {
Employee e1 = Employee(101, "Vinh", 500);
Employee e2(102, "Hoa", 1000);
e1.display();
e2.display();
return 0;
}
NHP, Khoa CNTT, Trường ĐHHHVN
Con trỏ this
NHP, Khoa CNTT, Trường ĐHHHVN
2.3. Cấu tử và hủy tử.
 Cấu tử (constructor): hàm thành phần có nhiệm vụ khởi tạo giá
trị ban đầu cho dữ liệu của đối tượng.
 Đặc điểm:
– trùng tên với tên lớp
– có nhãn public
– không có kiểu trả về
– có hoặc không có tham số (hàm tạo ngầm định)
– tự động được gọi khi đt được khai báo
– nếu không xd tường minh thì chương trình tự sinh ra một hàm tạo
không tham số, không nội dung
NHP, Khoa CNTT, Trường ĐHHHVN
Cấu tử
class MyClass{
const int ci;
int x;
public:
MyClass():ci(0),x(0){}
};
hoặc MyClass(): ci(0){x=0;}
NHP, Khoa CNTT, Trường ĐHHHVN
Cấu tử
class PS{
int ts, ms;
public:
PS():ts(1), ms(2){}
PS(int t, int m=9){ts=t; ms=m;}
};
PS a; // dùng hàm mặc định
PS b(2); // dùng hàm có tham số
PS x[10], y[5]={{3}, {5, 6}, 7, PS(2, 3)};
NHP, Khoa CNTT, Trường ĐHHHVN
Cấu tử sao chép (Copy Constructor)
 Nhiệm vụ của hàm thiết lập sao chép là tạo ra một đối tượng giống hệt
một đối t­
ượng đã có.
 Tạo đối tượng mới và sao chép nội dung của đối tượng cũ sang đối
tượng mới.
 ten_lop (const ten_lop &obj)
{
// phần thân của copy constructor
}
NHP, Khoa CNTT, Trường ĐHHHVN
Huỷ tử (Destructor)
 Là phương thức dùng để huỷ bỏ đối tượng
 Chỉ có duy nhất một hàm hủy trong một lớp.
 Có tên trùng với tên lớp, có dấu ~ phía trước.
 Không có tham số.
 Không có kiểu trả về.
 Được gọi tự động khi đối tượng đi ra khỏi phạm vi:
– Kết thúc hàm
– Kết thúc chương trình
– Kết thúc một block
– Toán tử delete được gọi
NHP, Khoa CNTT, Trường ĐHHHVN
Cấu tử, huỷ tử, cấu tử sao chép
NHP, Khoa CNTT, Trường ĐHHHVN
2.4. Thành phần tĩnh, hàm bạn, lớp bạn
 Thành phần tĩnh:
– Thuộc tính tĩnh
– Phương thức tĩnh
 Hàm bạn, lớp bạn
NHP, Khoa CNTT, Trường ĐHHHVN
2.4. Thành phần tĩnh, ...
 Thuộc tính tĩnh (static attribute) là những thuộc tính thuộc về bản
thân lớp chứ không thuộc về bất cứ thực thể nào của nó.
 1 thuộc tính tĩnh sẽ giống như 1 biến toàn thể, nghĩa là có thể
được truy cập từ bất cứ đâu trong đoạn mã
 Khai báo: thêm từ khoá static vào đầu dòng khai báo thuộc tính
 class Ten_Lop{
static int x;
int y;
public:
Ten_Lop(){...}
};
Khởi tạo giá trị thuộc tính static ở bên ngoài lớp
int Ten_Lop::x = 5;
NHP, Khoa CNTT, Trường ĐHHHVN
2.4. Thành phần tĩnh, ...
 Phương thức tĩnh (static method) là những phương thức thuộc về
bản thân lớp chứ không thuộc về bất cứ thực thể nào của nó.
 Có thể coi là những hàm bình thường được xếp vào trong khai
báo lớp nhưng lại không tác động gì đến các thuộc tính của lớp.
class TenLop{
public:
TenLop();
static void phuongThuc();
};
void TenLop::phuongThuc(){
cout << "Xin chao !" << endl;
}
int main(){
TenLop::phuongThuc();
TenLop a;
a.phuongThuc(); //sai
return 0;
}
NHP, Khoa CNTT, Trường ĐHHHVN
2.4. Thành phần tĩnh – ví dụ
#include <iostream>
using namespace std;
class PS{
public:
PS(int t, int m);
~PS();
static int soThucThe();
private:
int ts, ms;
static int soLuong;
};
int PS::soLuong = 0;
PS::PS(int t, int m) : ts(t), ms(m){
soLuong++;
}
PS::~PS(){
soLuong--;
}
int PS::soThucThe(){
return soLuong; //Tra ve gia trị cua bien dem
}
int main(){
PS x(1, 2);
PS y(3, 5);
cout << "Da tao ra " << PS::soThucThe() << " phan so." << endl;
return 0;
}
NHP, Khoa CNTT, Trường ĐHHHVN
2.4. ...hàm bạn, lớp bạn
 Trong OOP, khái niệm quan hệ bạn ( friend ) nghĩa là trao quyền truy cập hoàn toàn tới tất
cả các thành viên của 1 lớp cho 1 hàm.
 Khi khai báo 1 hàm bạn đồng nghĩa với việc chúng ta hủy hoàn toàn tính đóng gói của lớp
bởi lẽ 1 đoạn mã bên ngoài lớp có thể dễ dàng thay đổi nội dung của lớp.
 Hàm tự do là bạn của lớp
 Hàm của lớp A là bạn của lớp B
 Lớp A là bạn của lớp B
NHP, Khoa CNTT, Trường ĐHHHVN
2.4. ...hàm bạn, lớp bạn
 Khai báo
class A{
//nội dung của A
friend void fct();
};
void fct(){
//nội dung hàm fct
}
class B;
class A{
//nội dung của A
friend class B;
};
class B{
//nội dung của B
};
NHP, Khoa CNTT, Trường ĐHHHVN
2.4. ...ví dụ
 Xây dựng lớp SV.
 Xây dựng hàm sắp xếp danh sách sv theo tên.
NHP, Khoa CNTT, Trường ĐHHHVN
2.4. ...ví dụ
 Cách 1: dùng hàm bạn
#include <iostream>
using namespace std;
class SV{
string ten;
int ma;
double d1, d2, d3;
public:
SV();
void nhap();
void in();
friend void sxep(SV a[], int spt);
};
void sxep(SV a[], int spt){
for(int i=0; i<spt-1; i++)
for(int j=i+1; j<spt; j++)
if(a[i].ten > a[j].ten)
{
SV tg=a[i];
a[i]=a[j];
a[j]=tg;
}
}
int main(){
SV a[100];
int spt;
//...
sxep(a, n);
//...
}
NHP, Khoa CNTT, Trường ĐHHHVN
2.4. ...ví dụ
 Cách 2: dùng lớp bạn
#include <iostream>
using namespace std;
class DSSV;
class SV{
string ten;
int ma;
double d1, d2, d3;
public:
SV();
void nhap();
void in();
friend class DSSV;
};
class DSSV{
int spt;
SV *a;
public:
void nhap();
void in();
void sxep();
};
void DSSV::sxep(){
for(int i=0; i<spt-1; i++)
for(int j=i+1; j<spt; j++)
if(a[i].ten > a[j].ten)
{
SV tg=a[i];
a[i]=a[j];
a[j]=tg;
}
}
int main(){
DSSV ds;
ds.nhap();
ds.sxep();
ds.in();
return 0;
}
NHP, Khoa CNTT, Trường ĐHHHVN
2.5. Chồng toán tử (operator overloading)
 Khái niệm chồng (quá tải) toán tử
 Ưu nhược điểm của chồng toán tử
 Cách quá tải hàm toán tử
 Khả năng và giới hạn của chồng toán tử
 Ví dụ một số toán tử cơ bản
NHP, Khoa CNTT, Trường ĐHHHVN
Khái niệm chồng toán tử
 Với biểu thức a+b, ký hiệu + tuỳ theo kiểu của a và b có thể biểu
thị:
– phép cộng hai số nguyên,
– phép cộng hai số thực độ chính xác đơn (float),
– phép cộng hai số thực chính xác đôi (double),
– phép cộng một số nguyên vào một con trỏ,
– Phép cộng 2 ma trận,
– Phép cộng 2 phân số,
– …
NHP, Khoa CNTT, Trường ĐHHHVN
Khái niệm chồng toán tử
 Ví dụ: Xây dựng lớp PS có:
– Thuộc tính: ts, ms
– Phương thức: khởi tạo, nhập, xuất
– Hàm bạn: cong(PS a, PS b) - cộng 2 phân số
– hoặc phương thức cong(…) – cộng 2 phân số
NHP, Khoa CNTT, Trường ĐHHHVN
Khái niệm chồng toán tử
class PS{
int ts, ms;
public:
PS(int t=1, int m=2){
ts=t;
ms=m;
}
void nhap();
void xuat();
friend PS cong(PS a, PS b);
};
PS cong(PS a, PS b)
{
PS c;
c.ts=a.ts*b.ms+a.ms*b.ts;
c.ms=a.ms*b.ms;
return c;
}
…
PS x , y(2, 3) , z(1, 5);
x = cong(y, z);
? x=y+z;
NHP, Khoa CNTT, Trường ĐHHHVN
Ví dụ-lớp PS
class PS{
int ts, ms;
public:
PS(int t=1, int m=2){
ts=t;
ms=m;
}
void nhap();
void xuat();
friend PS operator+(PS a, PS b);
};
PS operator+(PS a, PS b)
{
PS c;
c.ts=a.ts*b.ms+a.ms*b.ts;
c.ms=a.ms*b.ms;
return c;
}
…
PS x, y(2, 3), z(1, 5);
x=y+z;//kết quả 13/15
NHP, Khoa CNTT, Trường ĐHHHVN
Khái niệm chồng toán tử
 Xét biểu thức a+b
+ là toán tử
a, b là toán hạng
 Một số toán tử trong C++
– các toán tử toán học: +, -, *, /, %
– các toán tử quan hệ: >, <, >=, <=, ==, !=
– toán tử logic: !, &&, ||
– toán tử >>, <<
– toán tử -, ++, --
– toán tử new, delete, sizeof, ?:
– .v.v.
NHP, Khoa CNTT, Trường ĐHHHVN
Khái niệm chồng toán tử
 Phân loại toán tử
– Toán tử một ngôi: -, ++, --, *, &, ~, !, sizeof (KIỂU)
– Toán tử 2 ngôi: +, -, *, /, >, <, ...
– Toán tử 3 ngôi: ?:
NHP, Khoa CNTT, Trường ĐHHHVN
Khái niệm chồng toán tử
Các hàm được
định nghĩa
chồng
Các toán tử
cũng là các hàm
(hàm toán tử)
Chồng toán tử là gì?
Các toán tử
cũng được định
nghĩa chồng
Định nghĩa lại các
toán tử sao cho
chúng có thể thực
hiện với các toán
hạng khác nhau.
NHP, Khoa CNTT, Trường ĐHHHVN
Ưu nhược điểm của chồng toán tử
 Làm cho các chương trình dễ viết hơn, cũng dễ hiểu hơn,
dễ bảo trì
 Có thể thay thế toán tử chồng bằng một hàm
 Chồng toán tử là cách duy nhất gọi một hàm KHÁC cách
gọi thông thường
– x=cong(y, z);
– x=y+z;
NHP, Khoa CNTT, Trường ĐHHHVN
Ví dụ: Xây dựng lớp PS
 Cách 1: có hàm cong(PS a, PS b) để cộng phân số a
và phân số b
 Cách 2: toán tử + để cộng phân số a và phân số b
NHP, Khoa CNTT, Trường ĐHHHVN
Quy tắc xây dựng hàm toán tử
 Hàm toán tử có thể được quá tải là phương thức của lớp hoặc hàm bạn:
– Nếu là phương thức thì số tham số của hàm bằng số ngôi của toán tử -1
– Nếu là hàm bạn thì số tham số của hàm bằng số ngôi
 Một trong số các toán hạng phải là đối tượng
 Khai báo: kiểu_hàm operator op(các tham số)
– op: là ký hiệu toán tử tương ứng
– operator: là từ khoá để khai báo hàm toán tử
– PS operator+(PS a, PS b);
NHP, Khoa CNTT, Trường ĐHHHVN
Cách xây dựng
kiểu_hàm operator op (các tham số)
{
//nội dung hàm toán tử
}
op: toán tử cần quá tải (+, -, *, /, …)
Tên hàm Dùng để
operator+ định nghĩa phép +
operator* định nghĩa phép nhân *
operator/ định nghĩa phép chia /
operator+= định nghĩa phép tự cộng +=
operator!= định nghĩa phép so sánh khác nhau
NHP, Khoa CNTT, Trường ĐHHHVN
Cách xây dựng
class PS{
int ts, ms;
public:
PS(int t=1, int m=2){
ts=t;
ms=m;
}
void nhap();
void xuat();
friend PS operator+(PS a, PS b);
};
PS operator+(PS a, PS b)
{
PS c;
c.ts=a.ts*b.ms + a.ms*b.ts;
c.ms=a.ms*b.ms;
return c;
}
…
PS x, y(2, 3), z(1, 5);
x=y+z;//kết quả 13/15
Nguyên mẫu
Định nghĩa hàm
Gọi hàm
x=operator+(y, z);
NHP, Khoa CNTT, Trường ĐHHHVN
Cách xây dựng
class PS{
int ts, ms;
public:
PS(int t=1, int m=2){
ts=t;
ms=m;
}
void nhap();
void xuat();
PS operator+(PS b);
};
PS PS::operator+(PS b)
{
PS c;
c.ts = this->ts * b.ms + this-> ms * b.ts;
c.ms = this->ms * b.ms;
return c;
}
…
PS x, y(2, 3), z(1, 5);
x=y+z;//kết quả 13/15
Nguyên mẫu
Định nghĩa hàm
Gọi hàm
x=y.operator+(z);
NHP, Khoa CNTT, Trường ĐHHHVN
Cách xây dựng- dạng hàm bạn
class PS{
int ts, ms;
public:
…
friend PS operator+(PS a, PS b);
friend PS operator-(PS a);
};
PS operator+(PS a, PS b){
PS c;
c.ts=a.ts*b.ms+a.ms*b.ts;
c.ms=a.ms*b.ms;
return c;
}
PS operator-(PS a){
a.ts=-a.ts;
return a;
}
…
x=y+z;//gọi hàm toán tử +
x=-t;//gọi hàm toán tử -
//x=operator+(y, z);
//x=operator-(t);
NHP, Khoa CNTT, Trường ĐHHHVN
Cách xây dựng-dạng hàm của lớp
class PS{
int ts, ms;
public:
PS operator+(PS b);
PS operator-();
};
PS PS::operator+(PS b){
PS c;
c.ts=ts*b.ms+ms*b.ts;
c.ms=ms*b.ms;
return c;
}
PS PS::operator-(){
ts=-ts;
return *this;
}
…
x=y+z; //gọi hàm toán tử +
x=-t; //gọi hàm toán tử -
//x=y. operator+(z);
//x=t.operator-();
NHP, Khoa CNTT, Trường ĐHHHVN
Quy tắc xây dựng
 Dạng phương thức: khuyết tham số thứ nhất (toán hạng thứ
nhất
 Toán hạng bên trái nhất của toán tử được overload phải là 1
đối tượng của kiểu class mà toán hạng khai báo.
 Toán hạng bên trái nhất trở thành tham số *this ngầm định.
Tất cả các toán hạng khác trở thành tham số hàm.
NHP, Khoa CNTT, Trường ĐHHHVN
Khả năng và giới hạn của chồng toán tử
 Phần lớn toán tử trong C++ đều có thể định nghĩa chồng, trừ các toán tử:
“::”, “.”, “?:” “ sizeof”, …
 Chỉ có thể overload các toán tử đã tồn tại.
 Phải giữ được thứ tự ưu tiên và tính kết hợp của toán hạng được overload.
 Các toán tử sau : =, [ ], ( ), -> phải được quá tải thông qua hàm thành viên
 <<, >>: phải được quá tải thông qua hàm bạn
 ++ và -- cần hai hàm toán tử khác nhau cho mỗi phép toán
NHP, Khoa CNTT, Trường ĐHHHVN
Một số ví dụ
 Quá tải toán tử so sánh
 Quá tải toán tử <<, >>
 Quá tải toán tử ++, --
 Quá tải toán tử =
 Quá tải toán tử [ ]
 Quá tải toán tử +=, -=, …
NHP, Khoa CNTT, Trường ĐHHHVN
Quá tải toán tử so sánh (>, <, …)
class PS{
int ts, ms;
public:
PS(int t=1, int m=2){ts=t; ms=m;}
friend bool operator>(PS a, PS b);
friend bool operator==(PS a, PS b);
};
bool operator>(PS a, PS b){
return (float)a.ts/a.ms>(float)b.ts/b.ms;
}
bool operator==(PS a, PS b){
return (float)a.ts/a.ms==(float)b.ts/b.ms;
}
main(){
PS x(2, 3), y(1, 5);
if(x==y) //operator==(x, y)
cout<<"Hai ps bang nhau";
else
cout<<"Hai ps ko bang nhau";
}
NHP, Khoa CNTT, Trường ĐHHHVN
Quá tải toán tử <<, >>
class PS{
…
friend istream &operator>>(istream &is, PS &x);
friend ostream &operator<<(ostream &os, PS &x);
};
istream &operator>>(istream &is, PS &x){
cout<<"Nhap tu so, mau so: ";
is>>x.ts>>x.ms;
return is;
}
ostream &operator<<(ostream &os, PS &x){
os<<x.ts<<"/"<<x.ms<<endl;
return os;
}
int main(){
PS a;
cout<<"Moi ban nhap dl:n";
cin>>a;
cout<<"nPhan so ban vua nhap: "<<a;
}
NHP, Khoa CNTT, Trường ĐHHHVN
Qúa tải toán tử <<, >>
class NV{
private:
string ten;
int manv;
float hsl;
public:
NV(string name="", int ma=0,float hs=0){
ten=name;
manv=ma;
hsl=hs;
}
friend istream &operator>>(istream &is, NV &p);
friend ostream &operator<<(ostream &os, NV &p);
friend bool operator>(NV p, NV q);
friend class DSNV;
};
istream &operator>>(istream &is, NV &p){
is>>p.ten;
is>>p.manv;
is>>p.hsl;
return is;
}
ostream &operator<<(ostream &os, NV &p){
os<<p.ten<<“ ”
<<p.manv<<“ ”
<<p.hsl<<endl;
return os;
}
bool operator > (NV p, NV q){
return p.hsl>q.hsl;
}
NHP, Khoa CNTT, Trường ĐHHHVN
Qúa tải toán tử <<, >>
class DSNV{
int snv;
NV *a;
public:
DSNV(int n=0){
snv=n;
a=NULL;
}
~DSNV(){
delete []a;
snv=0;
}
NV &operator[](int i){
return a[i];
}
friend istream &operator>>(istream &is, DSNV &p);
friend ostream &operator<<(ostream &os, DSNV &p);
void sxep();
};
NHP, Khoa CNTT, Trường ĐHHHVN
Quá tải toán tử ++, --
 Toán tử ++ và – có 2 dạng sử dụng là đứng trước và đứng sau
toán hạng
 Ví dụ: ++a hoặc a++ (--a hoặc a--)
 Cần xây dựng 2 dạng hàm chồng cho mỗi toán tử trên
– operator++() cho dạng ++a
– operator++(int) cho dạng a++
NHP, Khoa CNTT, Trường ĐHHHVN
Toán tử ++, --
#include<iostream>
using namespace std;
class PS{
int ts, ms;
public:
PS(int t=1, int m=2){
ts=t;
ms=m;
}
friend istream &operator>>(istream &is, PS &p);
friend ostream &operator<<(ostream &os, PS &p);
PS& operator++();//++x
PS& operator++(int);//x++
};
PS& PS::operator++(){
++ts;
return *this;
}
//////////////////////////////////////
PS& PS::operator++(int){
static PS temp;
temp.ts=ts;
temp.ms=ms;
ts++;
return temp;
}
NHP, Khoa CNTT, Trường ĐHHHVN
Toán tử ++, --
istream &operator>>(istream &is, PS &p){
cout<<"Nhap ts, ms: ";
is>>p.ts>>p.ms;
return is;
}
//////////////////////////////////////////////////////
ostream &operator<<(ostream &os, PS &p){
os<<p.ts<<"/"<<p.ms<<endl;
return os;
}
int main()
{
PS a(1,2);
cout<<a;
++a;
cout<<a;
a++;
cout<<a;
PS b;
b=a++;//b=3/2, a=4/2
cout<<"a= "<<a<<"b= "<<b;
PS c;
c = ++a;
cout<<"a= "<<a<<"c= "<<c;
}
Overload toán tử [ ]
Chỉ có thể overload toán tử [ ] thông qua hàm thành viên.
Lý do của việc hàm quá tải return một tham chiếu là vì vế trái của
toán tử gán ( = ) phải là một l-value.
Giá trị được return bằng tham chiếu hoặc con trỏ có thể là l-value
hoặc r-value. Giá trị được return bằng giá trị chỉ có thể là r-value.
l-value là 1 giá trị có địa chỉ.
Nên kiểm tra giá trị của index có ra ngoài phạm vi index của mảng
hay không.
Overload toán tử [ ]
class DS {
public:
float &operator [] (int index);
DS();
private:
float *a;
int spt;
};
float &DS::operator[] (int index) {
return (*this).(*(a+index));
}
float & operator[](int i) {
return a[i];
}
NHP, Khoa CNTT, Trường ĐHHHVN
Qúa tải toán tử [ ] - Phải là hàm của lớp
class DS{
int spt;
PS *a;
public:
DS(int n=5){
spt=n;
a=new PS[spt];
}
friend istream &operator>>(istream &is, DS &p);
friend ostream &operator<<(ostream &os, DS &p);
//void sxep();
PS& operator[](int i);//phai la ham cua lop
DS& operator=(DS &b);//phai la ham cua lop
};
DS& DS::operator=(DS &b){
if(this==&b){cout<<"nHai dt la mot";}
else{
delete a;
a=new PS[spt=b.spt];
for(int i=0; i<spt; i++)
a[i]=b.a[i];
}
return *this;
}
///////////////////////////////////////
PS& DS::operator[](int i){
if(0<=i && i<spt) return a[i];
}
NHP, Khoa CNTT, Trường ĐHHHVN
Quá tải toán tử [ ] - Phải là hàm của lớp
stream &operator>>(istream &is, DS &p){
cout<<"Nhap so phant tu: "; is>>p.spt;
p.a=new PS[p.spt];
for(int i=0; i<p.spt; i++)
is>>p[i];//is>>p.operator[](i);
return is;
}
///////////////////////////////////////
ostream &operator<<(ostream &os, DS &p){
for(int i=0; i<p.spt; i++)
os<<p[i];//os<<p.operator[](i);
return os;
}
int main(){
DS x;
cin>>x;
cout<<x;
cout<<"ps thu 3 "<<x[2];
}
Quá tải toán tử [ ] - Phải là hàm của lớp
class NV{
private:
string ten;
int manv;
float hsl;
public:
NV(string name="", int ma=0,float hs=0){
ten=name;
manv=ma;
hsl=hs;
}
friend istream &operator>>(istream &is, NV &p);
friend ostream &operator<<(ostream &os, NV &p);
friend bool operator>(NV p, NV q);
friend class DSNV;
};
Quá tải toán tử [ ] - Phải là hàm của lớp
class DSNV{
int snv;
NV *a;
public:
DSNV(int n=0){
snv=n;
a=NULL;
}
~DSNV(){
delete []a;
snv=0;
}
NV &operator[](int i){
return a[i];
}
friend istream &operator>>(istream &is, DSNV &p);
friend ostream &operator<<(ostream &os, DSNV &p);
void sxep();
};
Toán tử gán =
 A=B; // hiểu là A.operator=(B);
 B có thể là tham trị hoặc tham chiếu
 Việc truyền bằng tham trị đòi hỏi sự có mặt của hàm thiết lập sao
chép, hơn thế nữa sẽ làm cho chương trình chạy chậm vì mất thời
gian sao chép một lượng lớn dữ liệu.
 Vì vậy, b sẽ được truyền cho hàm operator= dưới dạng tham
chiếu.
Toán tử gán
DS &operator=(DS & p);//bổ sung vào khai báo lớp
DS &DS::operator=(DS &p) {
if (this !=&p){
delete v;
a=new float [spt=p.spt];
for(int i=0; i<n; i++) *(a+i)=p.(*(a+i));
}
else cout<<"Hai doi tuong la motn";
return *this;
}

More Related Content

PDF
Chuong8 (2)
DOC
Chuong 5
PDF
PPT
Chuong9 lop vadoituong
PPT
Chapter 4
PDF
Chuong3 c
PPTX
lap trinh huong doi tuong lap trinh huong doi tuonglap trinh huong doi tuongl...
PPT
Chapter 3 (cont)
Chuong8 (2)
Chuong 5
Chuong9 lop vadoituong
Chapter 4
Chuong3 c
lap trinh huong doi tuong lap trinh huong doi tuonglap trinh huong doi tuongl...
Chapter 3 (cont)

Similar to Lớp_Đối tượng............................... (20)

PDF
Bai05 ket tapvakethua
PPT
Chapter 3
PDF
OOP_01_Tong Quan LTHDT.pdf
PDF
PPT
Chapter 6
PDF
Đề thi 02
PPT
On thitotnghiep
PPTX
BHTCNPM-Slide-OOPppppppppppp-TH-22-23 .pptx
PDF
Ket tap, ke thua
DOCX
Bai tap thuc hanh
DOC
Chuong 3
PDF
10. C - Function And Operator Overload
DOC
Chuong 1
PDF
Pplthdt c02 lop_doi_tuong_v13.09a
PDF
bai giang Matlab
DOCX
Lappj trình hướng đối tượng
PDF
PDF
Chuong5 (2)
DOC
Chuong 6
DOC
Chuong 4
Bai05 ket tapvakethua
Chapter 3
OOP_01_Tong Quan LTHDT.pdf
Chapter 6
Đề thi 02
On thitotnghiep
BHTCNPM-Slide-OOPppppppppppp-TH-22-23 .pptx
Ket tap, ke thua
Bai tap thuc hanh
Chuong 3
10. C - Function And Operator Overload
Chuong 1
Pplthdt c02 lop_doi_tuong_v13.09a
bai giang Matlab
Lappj trình hướng đối tượng
Chuong5 (2)
Chuong 6
Chuong 4
Ad

Lớp_Đối tượng...............................

  • 1. NHP, Khoa CNTT, Trường ĐHHHVN Chương 2. Đối tượng và lớp 2.1. Định nghĩa đối tượng, lớp. 2.2. Khai báo lớp, đối tượng. 2.3. Cấu tử và hủy tử. 2.4. Thành phần tĩnh, hàm bạn, lớp bạn. 2.5. Định nghĩa chồng toán tử.
  • 2. NHP, Khoa CNTT, Trường ĐHHHVN 2.1. Định nghĩa đối tượng, lớp.  Đối tượng (object): là một thực thể tồn tại trong hệ thống. Mỗi đối tượng xác định bằng 3 yếu tố:  định danh đối tượng: xác định duy nhất đt trong hệ thống, phân biệt các đt với nhau  trạng thái của đt: là các thuộc tính mô tả đt  hoạt động của đt: là những hành động mà đt có thể thực hiện được.
  • 3. NHP, Khoa CNTT, Trường ĐHHHVN 2.1. Định nghĩa đối tượng, lớp. Ví dụ: Bài toán quản lý nhân viên, mỗi nhân viên là một đối tượng. – Nhân viên tên là Huy, tuổi 28, hệ số lương 3.00; … là một đối tượng, Kết quả của việc trừu tượng hóa các đối tượng của thế giới thực thành các đối tượng lập trình là sự kết hợp giữa dữ liệu (thuộc tính) và các hàm (phương thức).
  • 4. NHP, Khoa CNTT, Trường ĐHHHVN 2.1. Định nghĩa đối tượng, lớp  Lớp (class) là một kiểu dữ liệu mới được dùng để định nghĩa các đối tượng.  Một lớp có vai trò như một kế hoạch hay một bản mẫu.  Việc viết hay tạo ra một lớp mới không sinh ra bất cứ một đối tượng nào trong chương trình.
  • 5. NHP, Khoa CNTT, Trường ĐHHHVN 2.2. Khai báo lớp, đối tượng Khai báo lớp class tên_lớp [: <kiểu thừa kế> lớp_cha]{ private: // Khai báo các thành phần dữ liệu (thuộc tính) riêng // Khai báo các phương thức (hàm) riêng protected: // Khai báo các thành phần dữ liệu được bảo vệ // Khai báo các phương thức được bảo vệ public: // Khai báo các thành phần dữ liệu chung // Khai báo các phương thức chung };
  • 6. NHP, Khoa CNTT, Trường ĐHHHVN Khai báo lớp  class SV{ private: string ten; int masv; float d1, d2, d3; public: SV(){ten=“”; masv=0; d1=d2=d3=0.0;} void nhap(); void xuat(); float tong(){return d1+d2+d3;}  }; void SV::nhap(){ cout<<“Nhap ten sv: ”; cin>>ten; cout<<“Nhap ma sv: ”; cin>>masv; cout<<“Nhap diem: ”; cin>>d1>>d2>>d3; } void SV::xuat(){ cout<<“Ho ten ”<<ten<<endl; cout<<“Ma sv: ”<<masv<<endl; cout<<“D mon 1: ”<<d1<<endl; cout<<“D mon 2: ”<<d2<<endl; cout<<“D mon 3: ”<<d3<<endl; cout<<“Tong diem: ”<<tong()<<endl; }
  • 7. NHP, Khoa CNTT, Trường ĐHHHVN Khai báo đối tượng  Giống như khai báo biến thông thường  Tên_lớp tên_đối_tượng;  Ví dụ:  SV a;  SV b[10];  SV *p;  … Truy cập:  tên_đối_tượng.tên_pt/tên_tp  tên_đối_tượng->tên_pt/tên_tp //với con trỏ a.ten a.nhap() a.tong() p->xuat() p->ns …
  • 8. NHP, Khoa CNTT, Trường ĐHHHVN Các thành phần trong lớp  Các từ khóa private, protected, public quy định phạm vi sử dụng của các tp dữ liệu hoặc pt. từ khóa trong lớp ngoài lớp bạn bè thừa kế pri x x pro x x x pub x x x x
  • 9. NHP, Khoa CNTT, Trường ĐHHHVN Con trỏ this  Tất cả các phương thức hoặc tp dữ liệu phải được gọi thông qua đối tượng nào đó,  Con trỏ this tham chiếu đến đối tượng đang gọi hàm thành phần,  Con trỏ this trong C++ là một từ khóa đề cập đến thể hiện hiện tại của lớp,
  • 10. NHP, Khoa CNTT, Trường ĐHHHVN Con trỏ this class Employee { private: int id; string name; float salary; public: Employee(int id, string name, float salary) { this->id = id; this->name = name; this->salary = salary; } void display() { cout << this->id << " " << this->name << " " << this->salary << endl; } }; int main() { Employee e1 = Employee(101, "Vinh", 500); Employee e2(102, "Hoa", 1000); e1.display(); e2.display(); return 0; }
  • 11. NHP, Khoa CNTT, Trường ĐHHHVN Con trỏ this
  • 12. NHP, Khoa CNTT, Trường ĐHHHVN 2.3. Cấu tử và hủy tử.  Cấu tử (constructor): hàm thành phần có nhiệm vụ khởi tạo giá trị ban đầu cho dữ liệu của đối tượng.  Đặc điểm: – trùng tên với tên lớp – có nhãn public – không có kiểu trả về – có hoặc không có tham số (hàm tạo ngầm định) – tự động được gọi khi đt được khai báo – nếu không xd tường minh thì chương trình tự sinh ra một hàm tạo không tham số, không nội dung
  • 13. NHP, Khoa CNTT, Trường ĐHHHVN Cấu tử class MyClass{ const int ci; int x; public: MyClass():ci(0),x(0){} }; hoặc MyClass(): ci(0){x=0;}
  • 14. NHP, Khoa CNTT, Trường ĐHHHVN Cấu tử class PS{ int ts, ms; public: PS():ts(1), ms(2){} PS(int t, int m=9){ts=t; ms=m;} }; PS a; // dùng hàm mặc định PS b(2); // dùng hàm có tham số PS x[10], y[5]={{3}, {5, 6}, 7, PS(2, 3)};
  • 15. NHP, Khoa CNTT, Trường ĐHHHVN Cấu tử sao chép (Copy Constructor)  Nhiệm vụ của hàm thiết lập sao chép là tạo ra một đối tượng giống hệt một đối t­ ượng đã có.  Tạo đối tượng mới và sao chép nội dung của đối tượng cũ sang đối tượng mới.  ten_lop (const ten_lop &obj) { // phần thân của copy constructor }
  • 16. NHP, Khoa CNTT, Trường ĐHHHVN Huỷ tử (Destructor)  Là phương thức dùng để huỷ bỏ đối tượng  Chỉ có duy nhất một hàm hủy trong một lớp.  Có tên trùng với tên lớp, có dấu ~ phía trước.  Không có tham số.  Không có kiểu trả về.  Được gọi tự động khi đối tượng đi ra khỏi phạm vi: – Kết thúc hàm – Kết thúc chương trình – Kết thúc một block – Toán tử delete được gọi
  • 17. NHP, Khoa CNTT, Trường ĐHHHVN Cấu tử, huỷ tử, cấu tử sao chép
  • 18. NHP, Khoa CNTT, Trường ĐHHHVN 2.4. Thành phần tĩnh, hàm bạn, lớp bạn  Thành phần tĩnh: – Thuộc tính tĩnh – Phương thức tĩnh  Hàm bạn, lớp bạn
  • 19. NHP, Khoa CNTT, Trường ĐHHHVN 2.4. Thành phần tĩnh, ...  Thuộc tính tĩnh (static attribute) là những thuộc tính thuộc về bản thân lớp chứ không thuộc về bất cứ thực thể nào của nó.  1 thuộc tính tĩnh sẽ giống như 1 biến toàn thể, nghĩa là có thể được truy cập từ bất cứ đâu trong đoạn mã  Khai báo: thêm từ khoá static vào đầu dòng khai báo thuộc tính  class Ten_Lop{ static int x; int y; public: Ten_Lop(){...} }; Khởi tạo giá trị thuộc tính static ở bên ngoài lớp int Ten_Lop::x = 5;
  • 20. NHP, Khoa CNTT, Trường ĐHHHVN 2.4. Thành phần tĩnh, ...  Phương thức tĩnh (static method) là những phương thức thuộc về bản thân lớp chứ không thuộc về bất cứ thực thể nào của nó.  Có thể coi là những hàm bình thường được xếp vào trong khai báo lớp nhưng lại không tác động gì đến các thuộc tính của lớp. class TenLop{ public: TenLop(); static void phuongThuc(); }; void TenLop::phuongThuc(){ cout << "Xin chao !" << endl; } int main(){ TenLop::phuongThuc(); TenLop a; a.phuongThuc(); //sai return 0; }
  • 21. NHP, Khoa CNTT, Trường ĐHHHVN 2.4. Thành phần tĩnh – ví dụ #include <iostream> using namespace std; class PS{ public: PS(int t, int m); ~PS(); static int soThucThe(); private: int ts, ms; static int soLuong; }; int PS::soLuong = 0; PS::PS(int t, int m) : ts(t), ms(m){ soLuong++; } PS::~PS(){ soLuong--; } int PS::soThucThe(){ return soLuong; //Tra ve gia trị cua bien dem } int main(){ PS x(1, 2); PS y(3, 5); cout << "Da tao ra " << PS::soThucThe() << " phan so." << endl; return 0; }
  • 22. NHP, Khoa CNTT, Trường ĐHHHVN 2.4. ...hàm bạn, lớp bạn  Trong OOP, khái niệm quan hệ bạn ( friend ) nghĩa là trao quyền truy cập hoàn toàn tới tất cả các thành viên của 1 lớp cho 1 hàm.  Khi khai báo 1 hàm bạn đồng nghĩa với việc chúng ta hủy hoàn toàn tính đóng gói của lớp bởi lẽ 1 đoạn mã bên ngoài lớp có thể dễ dàng thay đổi nội dung của lớp.  Hàm tự do là bạn của lớp  Hàm của lớp A là bạn của lớp B  Lớp A là bạn của lớp B
  • 23. NHP, Khoa CNTT, Trường ĐHHHVN 2.4. ...hàm bạn, lớp bạn  Khai báo class A{ //nội dung của A friend void fct(); }; void fct(){ //nội dung hàm fct } class B; class A{ //nội dung của A friend class B; }; class B{ //nội dung của B };
  • 24. NHP, Khoa CNTT, Trường ĐHHHVN 2.4. ...ví dụ  Xây dựng lớp SV.  Xây dựng hàm sắp xếp danh sách sv theo tên.
  • 25. NHP, Khoa CNTT, Trường ĐHHHVN 2.4. ...ví dụ  Cách 1: dùng hàm bạn #include <iostream> using namespace std; class SV{ string ten; int ma; double d1, d2, d3; public: SV(); void nhap(); void in(); friend void sxep(SV a[], int spt); }; void sxep(SV a[], int spt){ for(int i=0; i<spt-1; i++) for(int j=i+1; j<spt; j++) if(a[i].ten > a[j].ten) { SV tg=a[i]; a[i]=a[j]; a[j]=tg; } } int main(){ SV a[100]; int spt; //... sxep(a, n); //... }
  • 26. NHP, Khoa CNTT, Trường ĐHHHVN 2.4. ...ví dụ  Cách 2: dùng lớp bạn #include <iostream> using namespace std; class DSSV; class SV{ string ten; int ma; double d1, d2, d3; public: SV(); void nhap(); void in(); friend class DSSV; }; class DSSV{ int spt; SV *a; public: void nhap(); void in(); void sxep(); }; void DSSV::sxep(){ for(int i=0; i<spt-1; i++) for(int j=i+1; j<spt; j++) if(a[i].ten > a[j].ten) { SV tg=a[i]; a[i]=a[j]; a[j]=tg; } } int main(){ DSSV ds; ds.nhap(); ds.sxep(); ds.in(); return 0; }
  • 27. NHP, Khoa CNTT, Trường ĐHHHVN 2.5. Chồng toán tử (operator overloading)  Khái niệm chồng (quá tải) toán tử  Ưu nhược điểm của chồng toán tử  Cách quá tải hàm toán tử  Khả năng và giới hạn của chồng toán tử  Ví dụ một số toán tử cơ bản
  • 28. NHP, Khoa CNTT, Trường ĐHHHVN Khái niệm chồng toán tử  Với biểu thức a+b, ký hiệu + tuỳ theo kiểu của a và b có thể biểu thị: – phép cộng hai số nguyên, – phép cộng hai số thực độ chính xác đơn (float), – phép cộng hai số thực chính xác đôi (double), – phép cộng một số nguyên vào một con trỏ, – Phép cộng 2 ma trận, – Phép cộng 2 phân số, – …
  • 29. NHP, Khoa CNTT, Trường ĐHHHVN Khái niệm chồng toán tử  Ví dụ: Xây dựng lớp PS có: – Thuộc tính: ts, ms – Phương thức: khởi tạo, nhập, xuất – Hàm bạn: cong(PS a, PS b) - cộng 2 phân số – hoặc phương thức cong(…) – cộng 2 phân số
  • 30. NHP, Khoa CNTT, Trường ĐHHHVN Khái niệm chồng toán tử class PS{ int ts, ms; public: PS(int t=1, int m=2){ ts=t; ms=m; } void nhap(); void xuat(); friend PS cong(PS a, PS b); }; PS cong(PS a, PS b) { PS c; c.ts=a.ts*b.ms+a.ms*b.ts; c.ms=a.ms*b.ms; return c; } … PS x , y(2, 3) , z(1, 5); x = cong(y, z); ? x=y+z;
  • 31. NHP, Khoa CNTT, Trường ĐHHHVN Ví dụ-lớp PS class PS{ int ts, ms; public: PS(int t=1, int m=2){ ts=t; ms=m; } void nhap(); void xuat(); friend PS operator+(PS a, PS b); }; PS operator+(PS a, PS b) { PS c; c.ts=a.ts*b.ms+a.ms*b.ts; c.ms=a.ms*b.ms; return c; } … PS x, y(2, 3), z(1, 5); x=y+z;//kết quả 13/15
  • 32. NHP, Khoa CNTT, Trường ĐHHHVN Khái niệm chồng toán tử  Xét biểu thức a+b + là toán tử a, b là toán hạng  Một số toán tử trong C++ – các toán tử toán học: +, -, *, /, % – các toán tử quan hệ: >, <, >=, <=, ==, != – toán tử logic: !, &&, || – toán tử >>, << – toán tử -, ++, -- – toán tử new, delete, sizeof, ?: – .v.v.
  • 33. NHP, Khoa CNTT, Trường ĐHHHVN Khái niệm chồng toán tử  Phân loại toán tử – Toán tử một ngôi: -, ++, --, *, &, ~, !, sizeof (KIỂU) – Toán tử 2 ngôi: +, -, *, /, >, <, ... – Toán tử 3 ngôi: ?:
  • 34. NHP, Khoa CNTT, Trường ĐHHHVN Khái niệm chồng toán tử Các hàm được định nghĩa chồng Các toán tử cũng là các hàm (hàm toán tử) Chồng toán tử là gì? Các toán tử cũng được định nghĩa chồng Định nghĩa lại các toán tử sao cho chúng có thể thực hiện với các toán hạng khác nhau.
  • 35. NHP, Khoa CNTT, Trường ĐHHHVN Ưu nhược điểm của chồng toán tử  Làm cho các chương trình dễ viết hơn, cũng dễ hiểu hơn, dễ bảo trì  Có thể thay thế toán tử chồng bằng một hàm  Chồng toán tử là cách duy nhất gọi một hàm KHÁC cách gọi thông thường – x=cong(y, z); – x=y+z;
  • 36. NHP, Khoa CNTT, Trường ĐHHHVN Ví dụ: Xây dựng lớp PS  Cách 1: có hàm cong(PS a, PS b) để cộng phân số a và phân số b  Cách 2: toán tử + để cộng phân số a và phân số b
  • 37. NHP, Khoa CNTT, Trường ĐHHHVN Quy tắc xây dựng hàm toán tử  Hàm toán tử có thể được quá tải là phương thức của lớp hoặc hàm bạn: – Nếu là phương thức thì số tham số của hàm bằng số ngôi của toán tử -1 – Nếu là hàm bạn thì số tham số của hàm bằng số ngôi  Một trong số các toán hạng phải là đối tượng  Khai báo: kiểu_hàm operator op(các tham số) – op: là ký hiệu toán tử tương ứng – operator: là từ khoá để khai báo hàm toán tử – PS operator+(PS a, PS b);
  • 38. NHP, Khoa CNTT, Trường ĐHHHVN Cách xây dựng kiểu_hàm operator op (các tham số) { //nội dung hàm toán tử } op: toán tử cần quá tải (+, -, *, /, …) Tên hàm Dùng để operator+ định nghĩa phép + operator* định nghĩa phép nhân * operator/ định nghĩa phép chia / operator+= định nghĩa phép tự cộng += operator!= định nghĩa phép so sánh khác nhau
  • 39. NHP, Khoa CNTT, Trường ĐHHHVN Cách xây dựng class PS{ int ts, ms; public: PS(int t=1, int m=2){ ts=t; ms=m; } void nhap(); void xuat(); friend PS operator+(PS a, PS b); }; PS operator+(PS a, PS b) { PS c; c.ts=a.ts*b.ms + a.ms*b.ts; c.ms=a.ms*b.ms; return c; } … PS x, y(2, 3), z(1, 5); x=y+z;//kết quả 13/15 Nguyên mẫu Định nghĩa hàm Gọi hàm x=operator+(y, z);
  • 40. NHP, Khoa CNTT, Trường ĐHHHVN Cách xây dựng class PS{ int ts, ms; public: PS(int t=1, int m=2){ ts=t; ms=m; } void nhap(); void xuat(); PS operator+(PS b); }; PS PS::operator+(PS b) { PS c; c.ts = this->ts * b.ms + this-> ms * b.ts; c.ms = this->ms * b.ms; return c; } … PS x, y(2, 3), z(1, 5); x=y+z;//kết quả 13/15 Nguyên mẫu Định nghĩa hàm Gọi hàm x=y.operator+(z);
  • 41. NHP, Khoa CNTT, Trường ĐHHHVN Cách xây dựng- dạng hàm bạn class PS{ int ts, ms; public: … friend PS operator+(PS a, PS b); friend PS operator-(PS a); }; PS operator+(PS a, PS b){ PS c; c.ts=a.ts*b.ms+a.ms*b.ts; c.ms=a.ms*b.ms; return c; } PS operator-(PS a){ a.ts=-a.ts; return a; } … x=y+z;//gọi hàm toán tử + x=-t;//gọi hàm toán tử - //x=operator+(y, z); //x=operator-(t);
  • 42. NHP, Khoa CNTT, Trường ĐHHHVN Cách xây dựng-dạng hàm của lớp class PS{ int ts, ms; public: PS operator+(PS b); PS operator-(); }; PS PS::operator+(PS b){ PS c; c.ts=ts*b.ms+ms*b.ts; c.ms=ms*b.ms; return c; } PS PS::operator-(){ ts=-ts; return *this; } … x=y+z; //gọi hàm toán tử + x=-t; //gọi hàm toán tử - //x=y. operator+(z); //x=t.operator-();
  • 43. NHP, Khoa CNTT, Trường ĐHHHVN Quy tắc xây dựng  Dạng phương thức: khuyết tham số thứ nhất (toán hạng thứ nhất  Toán hạng bên trái nhất của toán tử được overload phải là 1 đối tượng của kiểu class mà toán hạng khai báo.  Toán hạng bên trái nhất trở thành tham số *this ngầm định. Tất cả các toán hạng khác trở thành tham số hàm.
  • 44. NHP, Khoa CNTT, Trường ĐHHHVN Khả năng và giới hạn của chồng toán tử  Phần lớn toán tử trong C++ đều có thể định nghĩa chồng, trừ các toán tử: “::”, “.”, “?:” “ sizeof”, …  Chỉ có thể overload các toán tử đã tồn tại.  Phải giữ được thứ tự ưu tiên và tính kết hợp của toán hạng được overload.  Các toán tử sau : =, [ ], ( ), -> phải được quá tải thông qua hàm thành viên  <<, >>: phải được quá tải thông qua hàm bạn  ++ và -- cần hai hàm toán tử khác nhau cho mỗi phép toán
  • 45. NHP, Khoa CNTT, Trường ĐHHHVN Một số ví dụ  Quá tải toán tử so sánh  Quá tải toán tử <<, >>  Quá tải toán tử ++, --  Quá tải toán tử =  Quá tải toán tử [ ]  Quá tải toán tử +=, -=, …
  • 46. NHP, Khoa CNTT, Trường ĐHHHVN Quá tải toán tử so sánh (>, <, …) class PS{ int ts, ms; public: PS(int t=1, int m=2){ts=t; ms=m;} friend bool operator>(PS a, PS b); friend bool operator==(PS a, PS b); }; bool operator>(PS a, PS b){ return (float)a.ts/a.ms>(float)b.ts/b.ms; } bool operator==(PS a, PS b){ return (float)a.ts/a.ms==(float)b.ts/b.ms; } main(){ PS x(2, 3), y(1, 5); if(x==y) //operator==(x, y) cout<<"Hai ps bang nhau"; else cout<<"Hai ps ko bang nhau"; }
  • 47. NHP, Khoa CNTT, Trường ĐHHHVN Quá tải toán tử <<, >> class PS{ … friend istream &operator>>(istream &is, PS &x); friend ostream &operator<<(ostream &os, PS &x); }; istream &operator>>(istream &is, PS &x){ cout<<"Nhap tu so, mau so: "; is>>x.ts>>x.ms; return is; } ostream &operator<<(ostream &os, PS &x){ os<<x.ts<<"/"<<x.ms<<endl; return os; } int main(){ PS a; cout<<"Moi ban nhap dl:n"; cin>>a; cout<<"nPhan so ban vua nhap: "<<a; }
  • 48. NHP, Khoa CNTT, Trường ĐHHHVN Qúa tải toán tử <<, >> class NV{ private: string ten; int manv; float hsl; public: NV(string name="", int ma=0,float hs=0){ ten=name; manv=ma; hsl=hs; } friend istream &operator>>(istream &is, NV &p); friend ostream &operator<<(ostream &os, NV &p); friend bool operator>(NV p, NV q); friend class DSNV; }; istream &operator>>(istream &is, NV &p){ is>>p.ten; is>>p.manv; is>>p.hsl; return is; } ostream &operator<<(ostream &os, NV &p){ os<<p.ten<<“ ” <<p.manv<<“ ” <<p.hsl<<endl; return os; } bool operator > (NV p, NV q){ return p.hsl>q.hsl; }
  • 49. NHP, Khoa CNTT, Trường ĐHHHVN Qúa tải toán tử <<, >> class DSNV{ int snv; NV *a; public: DSNV(int n=0){ snv=n; a=NULL; } ~DSNV(){ delete []a; snv=0; } NV &operator[](int i){ return a[i]; } friend istream &operator>>(istream &is, DSNV &p); friend ostream &operator<<(ostream &os, DSNV &p); void sxep(); };
  • 50. NHP, Khoa CNTT, Trường ĐHHHVN Quá tải toán tử ++, --  Toán tử ++ và – có 2 dạng sử dụng là đứng trước và đứng sau toán hạng  Ví dụ: ++a hoặc a++ (--a hoặc a--)  Cần xây dựng 2 dạng hàm chồng cho mỗi toán tử trên – operator++() cho dạng ++a – operator++(int) cho dạng a++
  • 51. NHP, Khoa CNTT, Trường ĐHHHVN Toán tử ++, -- #include<iostream> using namespace std; class PS{ int ts, ms; public: PS(int t=1, int m=2){ ts=t; ms=m; } friend istream &operator>>(istream &is, PS &p); friend ostream &operator<<(ostream &os, PS &p); PS& operator++();//++x PS& operator++(int);//x++ }; PS& PS::operator++(){ ++ts; return *this; } ////////////////////////////////////// PS& PS::operator++(int){ static PS temp; temp.ts=ts; temp.ms=ms; ts++; return temp; }
  • 52. NHP, Khoa CNTT, Trường ĐHHHVN Toán tử ++, -- istream &operator>>(istream &is, PS &p){ cout<<"Nhap ts, ms: "; is>>p.ts>>p.ms; return is; } ////////////////////////////////////////////////////// ostream &operator<<(ostream &os, PS &p){ os<<p.ts<<"/"<<p.ms<<endl; return os; } int main() { PS a(1,2); cout<<a; ++a; cout<<a; a++; cout<<a; PS b; b=a++;//b=3/2, a=4/2 cout<<"a= "<<a<<"b= "<<b; PS c; c = ++a; cout<<"a= "<<a<<"c= "<<c; }
  • 53. Overload toán tử [ ] Chỉ có thể overload toán tử [ ] thông qua hàm thành viên. Lý do của việc hàm quá tải return một tham chiếu là vì vế trái của toán tử gán ( = ) phải là một l-value. Giá trị được return bằng tham chiếu hoặc con trỏ có thể là l-value hoặc r-value. Giá trị được return bằng giá trị chỉ có thể là r-value. l-value là 1 giá trị có địa chỉ. Nên kiểm tra giá trị của index có ra ngoài phạm vi index của mảng hay không.
  • 54. Overload toán tử [ ] class DS { public: float &operator [] (int index); DS(); private: float *a; int spt; }; float &DS::operator[] (int index) { return (*this).(*(a+index)); } float & operator[](int i) { return a[i]; }
  • 55. NHP, Khoa CNTT, Trường ĐHHHVN Qúa tải toán tử [ ] - Phải là hàm của lớp class DS{ int spt; PS *a; public: DS(int n=5){ spt=n; a=new PS[spt]; } friend istream &operator>>(istream &is, DS &p); friend ostream &operator<<(ostream &os, DS &p); //void sxep(); PS& operator[](int i);//phai la ham cua lop DS& operator=(DS &b);//phai la ham cua lop }; DS& DS::operator=(DS &b){ if(this==&b){cout<<"nHai dt la mot";} else{ delete a; a=new PS[spt=b.spt]; for(int i=0; i<spt; i++) a[i]=b.a[i]; } return *this; } /////////////////////////////////////// PS& DS::operator[](int i){ if(0<=i && i<spt) return a[i]; }
  • 56. NHP, Khoa CNTT, Trường ĐHHHVN Quá tải toán tử [ ] - Phải là hàm của lớp stream &operator>>(istream &is, DS &p){ cout<<"Nhap so phant tu: "; is>>p.spt; p.a=new PS[p.spt]; for(int i=0; i<p.spt; i++) is>>p[i];//is>>p.operator[](i); return is; } /////////////////////////////////////// ostream &operator<<(ostream &os, DS &p){ for(int i=0; i<p.spt; i++) os<<p[i];//os<<p.operator[](i); return os; } int main(){ DS x; cin>>x; cout<<x; cout<<"ps thu 3 "<<x[2]; }
  • 57. Quá tải toán tử [ ] - Phải là hàm của lớp class NV{ private: string ten; int manv; float hsl; public: NV(string name="", int ma=0,float hs=0){ ten=name; manv=ma; hsl=hs; } friend istream &operator>>(istream &is, NV &p); friend ostream &operator<<(ostream &os, NV &p); friend bool operator>(NV p, NV q); friend class DSNV; };
  • 58. Quá tải toán tử [ ] - Phải là hàm của lớp class DSNV{ int snv; NV *a; public: DSNV(int n=0){ snv=n; a=NULL; } ~DSNV(){ delete []a; snv=0; } NV &operator[](int i){ return a[i]; } friend istream &operator>>(istream &is, DSNV &p); friend ostream &operator<<(ostream &os, DSNV &p); void sxep(); };
  • 59. Toán tử gán =  A=B; // hiểu là A.operator=(B);  B có thể là tham trị hoặc tham chiếu  Việc truyền bằng tham trị đòi hỏi sự có mặt của hàm thiết lập sao chép, hơn thế nữa sẽ làm cho chương trình chạy chậm vì mất thời gian sao chép một lượng lớn dữ liệu.  Vì vậy, b sẽ được truyền cho hàm operator= dưới dạng tham chiếu.
  • 60. Toán tử gán DS &operator=(DS & p);//bổ sung vào khai báo lớp DS &DS::operator=(DS &p) { if (this !=&p){ delete v; a=new float [spt=p.spt]; for(int i=0; i<n; i++) *(a+i)=p.(*(a+i)); } else cout<<"Hai doi tuong la motn"; return *this; }

Editor's Notes

  • #9: Con trỏ this trỏ vào đối tượng đang gọi phương thức
  • #15: #include <iostream> using namespace std; class NV{ string ten; int ma; float hsl; int pc; public: NV(){ ten=""; ma=0; hsl=0.0; pc=0; } NV(const NV &p){ this->ten=p.ten; this->ma=p.ma; this->hsl=p.hsl; this->pc=p.pc; } void nhap(); void in(); float luong(){return hsl*1490+pc;} }; int main() { NV a; a.nhap(); //Huy, 101, 3.66, 1000 NV b(a); //Huy, 101, 3.66, 1000 return 0; } #include <iostream> using namespace std; class Day_so{ int spt; float *a; public: Day_so(){ spt=0; a=NULL; } Day_so(const Day_so &p){ this->spt=p.spt; this->a=new float[this->spt]; for(int i=0; i<this->spt; i++) a[i]=p.a[i]; } void nhap(); void in(); }; void Day_so::nhap(){ cin>>spt; a=new float[spt]; for(int i=0; i<spt; i++) cin>>a[i]; } void Day_so::in(){ for(int i=0; i<spt; i++) cout<<a[i]<<" "; cout<<endl; } int main() { Day_so ds1; ds1.nhap(); ds1.in(); Day_so ds2(ds1); ds2.in(); return 0; }
  • #19: không thể khởi tạo giá trị của nó tại đây mà phải thực hiện trong 1 không gian chung, nghĩa là nằm ngoài tất cả các khai báo lớp cũng như nằm ngoài tất cả các xử lý hàm.
  • #20: Xây dựng lớp DS có các hàm sắp xếp, tìm Max, Min mà ko cần phải tạo ra đối tượng (tức là có thể sắp xếp, tìm max, min, … của dãy số bình thường-ko phải đổi tượng)
  • #34: biểu thức a + b sẽ gọi tới một hàm cộng hai số nguyên nếu a và b thuộc kiểu int nhưng sẽ gọi tới một hàm khác nếu chúng là các đối tượng của một lớp nào đó mà chúng ta mới tạo ra.
  • #41: Hàm đảo dấu (-) ở trên không tác động lên toán hạng, chỉ sử dụng trong các biểu thức: ví dụ x=-y+z; thì được; nhưng –y; thì y vẫn không đổi
  • #44: hai phép toán ++ và -- có thể sử dụng theo hai cách khác nhau ứng với dạng tiền tố ++a, --b và dạng hậu tố a++, b--. Điều này đòi hỏi hai hàm toán tử khác nhau
  • #59: Việc truyền bằng tham trị đòi hỏi sự có mặt của hàm thiết lập sao chép, hơn thế nữa sẽ làm cho chương trình chạy chậm vì mất thời gian sao chép một lượng lớn dữ liệu. Vì vậy, b sẽ được truyền cho hàm operator= dưới dạng tham chiếu. Giá trị trả về của hàm operator= phụ thuộc vào mục đích sử dụng của biểu thức gán. Chúng ta chọn giải pháp trả về tham chiếu của đối tượng đứng bên trái dấu bằng nhằm giữ hai tính chất quan trong của biểu thức gán: (i) trật tự kết hợp từ bên phải sang trái, (ii) có thể sử dụng kết quả biểu thức gán trong các biểu thức khác. Ngoài ra giải pháp này cũng hạn chế việc sao chép dữ liệu từ nơi này đi nơi khác trong bộ nhớ.