You are on page 1of 47

om

.c
Lập trình

ng
co
an
Chương 4: Lớp và đối tượng
th
o ng
du
u
cu

2/10/2017
CuuDuongThanCong.com https://fb.com/tailieudientucntt
Nội dung
 4.1 Khái niệm

om
 4.2 Định nghĩa lớp
 4.3 Biến thành viên

.c
 4.4 Hàm thành viên

ng
 4.5 Kiểm soát truy nhập

co
 4.6 Bài tập phần 1

an
 4.7 Hàm tạo và hàm hủy
 4.8 Hàm tạo bản sao
th
ng
 4.9 Hàm toán tử gán
o
du

 4.10 Thành viên tĩnh


u

 4.11 Nạp chồng toán tử


cu

 4.12 Khai báo friend

Chương 4: Lớp và đối tượng 2


CuuDuongThanCong.com https://fb.com/tailieudientucntt
4.1 Khái niệm
 Đối tượng là gì?

om
– Mô hình đại diện của một đối tượng vật lý:

.c
 Person, student, employee, employer
 Car, bus, vehicle,…

ng
– Đối tượng logic

co
 Trend, report, button, window,…

an
 Một đối tượng có:

th
– Các thuộc tính
ng
– Trạng thái
o
du

– Hành vi
u

– Căn cước
cu

– Ngữ nghĩa

Chương 4: Lớp và đối tượng 3


CuuDuongThanCong.com https://fb.com/tailieudientucntt
Lớp là gì?
 Là sự thực thi của các đối tượng có chung các thuộc

om
tính, hành vi, quan hệ, ngữ nghĩa.

.c
 Lớp là một kiểu dữ liệu mới có cấu trúc, trong đó việc

ng
truy nhập các biến thành viên được kiểm soát thông

co
qua các hàm thành viên.
 Các dữ liệu của lớp  biến thành viên

an
th
 Các hàm của lớp  hàm thành viên ng
 Một biến của một lớp  một đối tượng
o
du
u
cu

Chương 4: Lớp và đối tượng 4


CuuDuongThanCong.com https://fb.com/tailieudientucntt
4.2 Định nghĩa lớp
 Kiểu dữ liệu có cấu trúc

om
sruct Date{
//sử dụng
void main(){
int day, month, year;

.c
Date d;
};
set_date(d,32,13,2010);
void set_date(Date& date,int d, int m, int y){

ng
add_day(d,5);
date.day = d;
add_year(d,1);
date.month = m;

co
d.month = 13;
date.year = y;
}
}

an
void add_day(Date& date, int n){

th
date.day += n;
...
ng
}
Truy nhập biến
void add_month(Date& date, int n) ){
o
thành viên từ
du

date.month += n;
... bên ngoài
}
u
cu

void add_year(Date& date, int n) ){


date.year += n;
}

Chương 4: Lớp và đối tượng 5


CuuDuongThanCong.com https://fb.com/tailieudientucntt
Các vấn đề với struct
 Truy nhập trực tiếp vào các biến thành viên của cấu
trúc  không an toàn

om
Khi có sự thay đổi tên của các biến thành viên 

.c

ng
người sử dụng phải thay đổi lại mã chương trình ứng

co
dụng
– Ví dụ: thay đổi lại cấu trúc Date

an
sruct Date{

th
int d, m, y; ng
};
o
– Thì đoạn mã sau sẽ có lỗi không biên dịch
du

Date d;
d.month = 10;
u
cu

Chương 4: Lớp và đối tượng 6


CuuDuongThanCong.com https://fb.com/tailieudientucntt
Lớp hóa
 Định nghĩa lớp Date
Tên lớp

om
class Date{
int day; Biến thành viên

.c
int month;
int year;

ng
public: Kiểm soát quyền

co
void set_date(int d, int m, int y){ truy nhập
day = d;

an
month = m;
year = y;

th
}
int get_day() { return day; } Hàm thành viên
ng
int get_month() { return month; }
o
int get_year() { return year; }
du

void add_year(int n) ){
year += n;
u

}
cu

...
};

Chương 4: Lớp và đối tượng 7


CuuDuongThanCong.com https://fb.com/tailieudientucntt
 Sử dụng lớp Date
Đối tượng

om
void main(){
Date d;

.c
d.set_date(1,1,2010);
d.add_year(10);

ng
d.day = 10; //?? Có lỗi.

co
d.month = 10; //?? day, month, year là
d.year = 2009;//??
các biến thành viên

an
int i = d.day;//??
int day = d.get_day(); của Date thuộc kiểu

th
int month = d.get_month(); không được phép
int year = d.get_year();
ng
truy nhập từ bên
}
ngoài (kiểu private)
o
du
u
cu

Chương 4: Lớp và đối tượng 8


CuuDuongThanCong.com https://fb.com/tailieudientucntt
 Thay đổi tên biến thành viên của lớp

om
class Date{ //Sử dụng
int d; void main{

.c
int m; Date d;
int y; d.set_date(1,1,2010);

ng
public: d.add_year(10);
int day = d.get_day();

co
void set_date(int _d, int _m, int _y){
d = _d; int month = d.get_month();
int year = d.get_year();

an
m = _m;
y = _y; }

th
}
int get_day() { return d; }
ng
int get_month() { return m; }
o
int get_year() { return y; }
du

void add_year(int n) ){
year += n;
Có sự khác
biệt
u

}
cu

... không?
};

Chương 4: Lớp và đối tượng 9


CuuDuongThanCong.com https://fb.com/tailieudientucntt
4.3 Biến thành viên
 Khai báo biến thành viên của lớp
class Date{

om
int day,month, year; //khai báo tưng tự như cấu trúc

.c
...
};

ng
 Mặc định các biến thành viên không truy nhập được từ bên

co
ngoài

an
Date d;

th
d.day = 10;; //Lỗi, vì biến thành viên day của Date thuộc kiểu private
ng
 Có thể cho phép biến thành viên truy nhập từ bên ngoài bằng
o
du

cách chuyển thành biến public. Tuy nhiên, ít khi sử dụng như
vậy vì không còn che giấu dữ liệu
u
cu

class Date{
public:
int day,month, year; //truy nhập được từ bên ngoài
...
};
Chương 4: Lớp và đối tượng 10
CuuDuongThanCong.com https://fb.com/tailieudientucntt
 Truy nhập các biến thành viên thông qua các hàm
thành viên
class Date{
int day, month,year;

om
public: Hàm thành viên
int get_day() { return day; } để truy nhập biến

.c
void set_day(int d){ day = d; } thành viên
};

ng
co
 Khởi tạo biến thành viên thông qua hàm tạo
class Date{

an
int day, month,year;

th
public:
ng
Date(int d, int m, int y){ //hàm tạo
o
day = d; month = m; year = y;
du

}
u

...
cu

};

Chương 4: Lớp và đối tượng 11


CuuDuongThanCong.com https://fb.com/tailieudientucntt
4.4 Hàm thành viên
 Khai báo và định nghĩa hàm thành viên
class Date{

om
int day, month,year;

.c
public: Khai báo và
int get_day() { return day; } định nghĩa

ng
void set_day(int d);

co
. . . Chỉ khai báo,
}; không định

an
void Date::set_day(int d){ nghĩa

th
day = d; ng
} Định nghĩa bên
ngoài phần khai
o
báo lớp
du

 Để che giấu cách thực hiện, hàm thành viên thường được khai
u

báo trong tập tin đầu (*.h), phần định nghĩa được thực hiện
cu

trong tệp tin nguồn (*.cpp). Khi đóng gói thành thư viện, người
sử dụng chỉ cần tệp tin thư viện (*.lib) và tệp tin đầu (*.h),
không cần tệp tin nguồn (*.cpp)

Chương 4: Lớp và đối tượng 12


CuuDuongThanCong.com https://fb.com/tailieudientucntt
 Khai báo hàm thành viên trong tệp tin đầu (*.h)
//tệp tin Date.h

om
class Date{
int day, month,year;

.c
public:

ng
int get_day();

co
void set_day(int d);
. . .

an
};

th
 Định hàm thành viên trong tệp tin nguồn (*.cpp)
o ng
//tệp tin Date.cpp
du

void Date::set_day(int d){


u

day = d;
cu

}
void Date::get_day(){ return day;}

Chương 4: Lớp và đối tượng 13


CuuDuongThanCong.com https://fb.com/tailieudientucntt
Con trỏ đối tượng
 Sử dụng con trỏ đối tượng

om
.c
void main{
Date d;

ng
d.set_date(1,1,2010);
Date *pd = &d;

co
//con trỏ pd trỏ vào đối tượng d
pd->set_date(1,1,2010);

an
Date *pd1 = new Date; //cấp phát bộ nhớ, gọi hàm tạo
pd1->set_day(10);

th
. . . ng
delete pd1; //hủy bộ nhớ
Date *pd2 = new Date[5];
o
du

for(int i = 0 ;i < 5; i++)


pd2[i].set_date(1,1,2010);
u

. . .
cu

delete [] pd2;
}

Chương 4: Lớp và đối tượng 14


CuuDuongThanCong.com https://fb.com/tailieudientucntt
4.5 Kiểm soát truy nhập
 private: các thành viên chỉ có thể truy nhập từ các

om
thành viên của lớp và từ các bạn bè của lớp

.c
 public: các thành viên công cộng, truy nhập được ở

ng
mọi nơi

co
 protected: các thành viên không truy nhập được từ

an
bên ngoài, nhưng truy nhập được từ lớp dẫn xuất

th
Lớp dẫn xuất
ng
class A{ class B: public A{
o
du

protected: public:
int a; void g(){ Lớp cơ sở
u

void f(); f();


cu

}; }
};

Chương 4: Lớp và đối tượng 15


CuuDuongThanCong.com https://fb.com/tailieudientucntt
4.6 Bài tập
 Xây dựng một lớp tên person để đại diện cho một

om
người với các yêu cầu:

.c
– Tên có độ dài tối đa 50 ký tự
– Ngày, tháng, năm sinh có kiểu int (hoặc thuộc kiểu Date như

ng
đã gợi ý trong bài giảng).

co
– Quê quán có độ dài tối đa 100 ký tự

an
– Hàm nhập tên, ngày sinh, quê từ bán phím

th
– Hàm hiển thị thông tin ra màn hình
ng
– Hàm lấy tên, hàm gán tên
o
du

– Hàm lấy quê quán, hàm gán quê quán


– Hàm lấy ngày sinh, hàm gan ngày sinh
u
cu

– Viết chương trình chính minh họa cách sử dụng

Chương 4: Lớp và đối tượng 16


CuuDuongThanCong.com https://fb.com/tailieudientucntt
4.7 Hàm tạo và hàm hủy
 Vấn đề 1: Nghiên cứu đoạn mã sau

om
class Date{
int day, month,year;

.c
public:
int get_day() { return day; }

ng
void set_day(int d){ day = d; }

co
}; Câu hỏi:
void main(){

an
d.day = ?
Date d; d.month = ?

th
int i = d.get_date(); d.year = ?
}
ng
 Làm thế nào để sau khi được tạo ra, đối tượng có
o
du

trạng thái ban đầu theo ý muốn của người sử dụng?


u

 Giải pháp: sử dụng hàm tạo


cu

Chương 4: Lớp và đối tượng 17


CuuDuongThanCong.com https://fb.com/tailieudientucntt
4.7 Hàm tạo và hàm hủy (…)
 Vấn đề 2: đối tượng sử dụng bộ nhớ động

om
class Array{
int n; //số phần tử của array

.c
int *data; //mảng chứa giá trị các phần tử
public:

ng
...
};

co
an
 Câu hỏi: làm thế nào để cấp phát bộ nhớ và hủy bộ

th
nhớ cho biến thành viên data một cách an toàn
ng
o
du

 Giải pháp: sử dụng hàm tạo và hàm hủy.


u
cu

Chương 4: Lớp và đối tượng 18


CuuDuongThanCong.com https://fb.com/tailieudientucntt
4.7 Hàm tạo và hàm hủy (…)
 Hàm tạo: luôn được gọi khi đối tượng được tạo ra

om
 Hàm hủy: luôn được gọi khi đối tượng bị hủy

.c
 Cú pháp:

ng
class A{
int a, b;

co
public:
A(){a = 0; b = 0;} 1

an
A(int _a){ a = _a;} 2

th
A(int _a, int _b){ a = _a; b = _b;} 3
~A();
ng
};
o
du

 Một lớp có thể có nhiều hàm tạo


u

– Hàm tạo 1: hàm tạo không đối


cu

– Hàm tạo 2: hàm tạo một đối


– Hàm tạo 3: hàm tạo hai đối
 Một lớp chỉ có duy nhất một hàm hủy
Chương 4: Lớp và đối tượng 19
CuuDuongThanCong.com https://fb.com/tailieudientucntt
 Sử dụng

void main{
A a(); //gọi hàm tạo (?)

om
A a1(10); //gọi hàm tạo (?)
A a2(1,2); //gọi hàm tạo (?)

.c
} //gọi hàm hủy cho ?

ng
co
void f(A a){ gọi hàm tạo (?)
A b(0,0);

an
if(...){ gọi hàm tạo (?)

th
A c;
... gọi hàm hủy cho ?
ng
}
o
du

} gọi hàm hủy cho ?


u
cu

void main{
A *a = new A(10); //gọi hàm tạo (?)
. . . //sử dụng
delete a; //gọi hàm hủy
}

Chương 4: Lớp và đối tượng 20


CuuDuongThanCong.com https://fb.com/tailieudientucntt
4.7 Hàm tạo và hàm hủy (…)
 Làm thế nào để không phải định nghĩa nhiều hàm

om
tạo như ví dụ trên?

.c
 Giải pháp: sử dụng hàm tạo có tham biến mặc định
 một lớp chỉ cần một hàm tạo duy nhất

ng
co
class A{
int a, b;

an
public:

th
A(int _a = 0, int _b = 0) { a = _a; b = _b;}
. . .
ng
};
o
du

void main{
A a1;
u

//a1.a = ?; a1.b = ?
cu

A a2(1); //a2.a = ?; a2.b = ?


A a3(1,2); //a3.a = ?; a3.b = ?
};

Chương 4: Lớp và đối tượng 21


CuuDuongThanCong.com https://fb.com/tailieudientucntt
Tóm tắt về hàm tạo và hàm hủy
 Hàm tạo được sử dụng để:
– Cấp phát bộ nhớ động

om
– Khởi tạo các trạng thái ban đầu cho đối tượng
 Một lớp có thể có nhiều hàm tạo. Chúng khác nhau ở số lượng

.c
các tham số hoặc kiểu của các tham số.

ng
 Nếu không định nghĩa hàm tạo thì compiler sẽ tự động sinh ra

co
một hàm tạo với mã thực thi là rỗng, dẫn đến:
– Trạng thái ban đầu của các biến thành viên là bất định

an
– Không cấp phát bộ nhớ động cho các biến thành viên dạng mảng

th
động
 Hàm hủy là duy nhất
ng
 Hàm hủy không bao giờ có đối
o
du

 Nếu không định nghĩa hàm hủy thì compiler cũng tự động sinh
ra nhưng mã thực thi của hàm hủy này là rỗng.
u
cu

 Khi sử dụng đối tượng động (có sử dụng toán tử new) thì luôn
phải nhớ hủy bộ nhớ đã cấp phát cho bộ nhớ động khi không cần
dùng đến chúng nữa (sử dụng toán tử delete)
 Hàm tạo và hàm hủy có thể được định nghĩa bên ngoài phần
khai báo lớp.
Chương 4: Lớp và đối tượng 22
CuuDuongThanCong.com https://fb.com/tailieudientucntt
Ví dụ về lớp Array
//sử dụng
//khai báo lớp Array void main(){
class Array{ Array a(5);

om
int n; Array *pa = new Array(5,1);
...
int *data;
delete pa;

.c
public: }
Array(int _n = 0, int _d = 0);

ng
~ Array();

co
. . .
}; Câu hỏi:

an
1. Các giá trị của mảng data của a, pa
//định nghĩa hàm tạo và hàm hủy bằng bao nhiêu?

th
Array :: Array(int _n, int _d){ 2. Không sử dụng delete pa có được
n = _n;
ng
không?
data = new int[n]; 3. Biến a được hủy khi nào?
o
for(int i = 0; i < n; i++)
du

data[i] = _d;
}
u

Array ::~ Array(){


cu

delete [] data;
}

Chương 4: Lớp và đối tượng 23


CuuDuongThanCong.com https://fb.com/tailieudientucntt
4.8 Hàm tạo bản sao
 Hàm tạo bản sao được gọi khi sao chép đối tượng

om
(xem các ví dụ sau)

.c
 Cú pháp chuẩn:
class A{

ng
Sao chép tham
int a, b;
số từ a1, a1

co
public:
A(const A& a1); không bị thay

an
. . . đổi do vô tình
};
//định nghĩa hàm sao chép
th
ng
A::A(const A& a1){
o
a = a1.a;
du

b = a1.b;
}
u

//sử dụng
cu

void main(){
A a; Gọi hàm tạo
A a1(a); bản sao
}

Chương 4: Lớp và đối tượng 24


CuuDuongThanCong.com https://fb.com/tailieudientucntt
 Hàm tạo bản sao được gọi khi sao chép đối tượng:
– Khi khai báo các biến x2-x4 như sau:
X x1;
X x2(x1);

om
X x3 = x1;
X x4 = X(x1);

.c
– Khi truyền tham số qua giá trị cho một hàm
void f(X x) { ... }

ng
ở đây có sự gọi hàm tạo bản
void main(){

co
sao để sao chép nội dung của
X a; a để truyền vào cho tham biến

an
f(a); hình thức x của hàm f

th
} ng
- Khi một hàm trả về một đối tượng
o
X f() {
du

X x1;
. . . //thực hiện thuật toán
u

return x1; ở đây có sự gọi hàm tạo bản sao để


cu

} sao chép nội dung của biến tạm x1


void main(){ sang cho biến x sau khi thực hiện
X x = f(); xong lệnh return trong hàm f
. . .
}
Chương 4: Lớp và đối tượng 25
CuuDuongThanCong.com https://fb.com/tailieudientucntt
 Nếu không định nghĩa hàm tạo bản sao thì compiler
sẽ tự sinh ra và sao chép từng bít
 Lớp không có tham biến được cấp phát động thì

om
không cần định nghĩa hàm tạo bản sao

.c
 Khi có tham biến được cấp phát động thì bắt buộc

ng
định nghĩa lại hàm tạo bản sao.

co
an
//khai báo lớp Array không có hàm tạo bản sao

th
class Array{
int n;
ng
int *data;
o
public:
du

Array(int _n = 0; int _d = 0) {...}


~ Array(){...}
u

void set_data(int i, int d){


cu

if((i>=0) && (i<n))


data[i] = d;
};

Chương 4: Lớp và đối tượng 26


CuuDuongThanCong.com https://fb.com/tailieudientucntt
//sử dụng Gọi hàm tạo bản
void main{ sao để sao chép
Array a(5,0); a sang b
Array b(a);

om
... Hỏi: a.data[0] =
b.set_data(0,10);

.c
?
};

ng
 Do không định nghĩa hàm tạo bản sao, nên ở đây gọi

co
hàm tạo bản sao mặc định do compiler sinh ra, hàm

an
tạo này có dạng:
th
Array :: Array(const Array & a){
ng
n = a.n;
o
data = a.data;
du

}
u

 Khi sử dụng Array b(a); thì mảng data của a và b là một, nên
cu

khi thay đổi b thì a sẽ thay đổi theo.

 Giải pháp: định nghĩa lại hàm tạo bản sao


Chương 4: Lớp và đối tượng 27
CuuDuongThanCong.com https://fb.com/tailieudientucntt
4.8 Hàm tạo bản sao (…)
 Định nghĩa hàm tạo bản sao cho lớp Array như sau

om
Array :: Array(const Array & a) {

.c
n = a.n;

ng
data = new int[n];
for (int i=0; i < n; ++i)

co
data[i] = a.data[i];

an
}

th
 Khi một lớp phải định nghĩa hàm hủy thì cũng cần
ng
thiết định nghĩa lại hàm tạo bản sao
o
du

 Trong trường hợp muốn cấm sao chép thì ta khai báo
u

hàm tạo bản sao trong phần private.


cu

Chương 4: Lớp và đối tượng 28


CuuDuongThanCong.com https://fb.com/tailieudientucntt
Con trỏ this
 Từ khóa this được dùng trong khi định nghĩa các

om
hàm thành viên dùng để trỏ đến đối tượng hiện tại

.c
 Nói chung, con trỏ this ít khi được sử dụng tường

ng
minh, vì nó đã được ngầm sử dụng khi truy nhập vào

co
các thành phần dữ liệu. Nó thường được sử dụng khi
chúng ta muốn lấy địa chỉ của đối tượng hiện tại (như

an
để trỏ vào chính đối tượng đó)
th
o ng
du
u
cu

Chương 4: Lớp và đối tượng 29/52


CuuDuongThanCong.com https://fb.com/tailieudientucntt
4.9 Hàm toán tử gán
 Nghiên cứu ví dụ 1:

om
class A{
int a, b;

.c
public:

ng
A(int _a, int _b):a(_a), b(_b){} //hàm tạo
. . .

co
};

an
Gọi hàm toán tử gán (=).
void main(){ ở đây sẽ có:

th
A a(1,2); b.a = a.a
A b; OK
ng
b.b = a.b
b = a;
o
}
du
u

 Không định nghĩa hàm toán tử gán, compiler sẽ tự


cu

động sinh ra và gán từng bít (giống với hàm tạo bản
sao)

Chương 4: Lớp và đối tượng 30


CuuDuongThanCong.com https://fb.com/tailieudientucntt
4.9 Hàm toán tử gán(…)
 Nghiên cứu ví dụ 2:

om
class Array{

.c
int n;
int *data;

ng
public:
Array(int _n = 0; int _d = 0) {...}

co
~ Array(){...}

an
...
};

th Gọi hàm toán tử gán (=).


ng
Void main() {
ở đây sẽ có:
Array a(5,1);
o
a1.n = a.n
du

Array a1;
a1.data = a.data
a1 = a;
u

}
cu

 a1.data và a.data cùng trỏ vào một vùng nhớ  kết quả tương
tự với trong trường hợp hàm tạo bản sao ở trên.
 Trong trường hợp này cần định nghĩa hàm toán tử gán
Chương 4: Lớp và đối tượng 31
CuuDuongThanCong.com https://fb.com/tailieudientucntt
4.9 Hàm toán tử gán(…)
 Cú pháp chuẩn hàm toán tử gán:

om
class A{

.c
...
public:

ng
A& operator=(const A&); //khái báo hàm toán tử gán

co
. . .

an
};

//định nghĩa hàm toán tử gán:


th
ng
A& A::operator=(const A& a1){
o
du

...//mã gán các biến thành viên


}
u
cu

Chương 4: Lớp và đối tượng 32


CuuDuongThanCong.com https://fb.com/tailieudientucntt
4.9 Hàm toán tử gán(…)
 Ví dụ định nghĩa hàm toán tử gán cho lớp Array

om
class Array{

.c
int n;
int *data;

ng
public:
Array(int _n = 0; int _d = 0) {...}

co
~Array(){...}

an
Array& operator=(const Array& a)
};

th
ng
Array& Array::operator=(const Array& a) {
if (n != a.n) {
o
du

delete [] data;
n = a.n;
u

data = new int[n];


cu

}
for (int i=0; i < n; ++i)
data[i] = a.data[i];
return *this;
}
Chương 4: Lớp và đối tượng 33
CuuDuongThanCong.com https://fb.com/tailieudientucntt
Bài tập
 Định nghĩa lớp Array có các yêu cầu sau

om
– Hàm tạo, hàm hủy, hàm tạo bản sao, hàm toán tử gán

.c
– Các hàm cho phép nhập dữ liệu vào từ bàn phím và hiển thị
ra màn hình cho Array

ng
– Các hàm cho phép thay đổi/đọc giá trị của một phần tử nào

co
đó trong Array

an
– Viết chương trình chính minh họa cách sử dụng

th
o ng
du
u
cu

Chương 4: Lớp và đối tượng 34


CuuDuongThanCong.com https://fb.com/tailieudientucntt
4.10 Thành viên tĩnh
 Biến thành viên tĩnh

om
 Vấn đề: Yêu cầu ghi lại số lượng các đối tượng được tạo ra từ lớp Date
void main(){

.c
Date d1(1,1,2010); // count++

ng
Date d2 = d1; // count++

co

}

an
 Giải pháp: đưa biến count là một biến static của lớp Date

th
class Date{ Date::Date(int d, int m, int y){
ng
int day, month,year; day = d; month = m; year = y;
count++;
o
static int count;
du

public: }
Date(int d, int m, int y); Date::Date(const Date& d){
u

Date(const Date& d); day = d.day; month = d.month;


cu

~Date(); year = y.year; count++;


. . . Khai báo }
}; biến tĩnh Date::~Date(){
int Date:: count = 0; count--;
} Định nghĩa biến tĩnh: bắt buộc và nằm
Chương 4: Lớp và đối tượng bên ngoài khai báo lớp và ngoài các35hàm
CuuDuongThanCong.com https://fb.com/tailieudientucntt
4.10 Thành viên tĩnh(…)
 Hàm thành viên tĩnh Trong hàm thành viên tĩnh chỉ sử dụng

om
class A{ được các biến thành viên tĩnh và chỉ gọi
int n; được các hàm thành viên tĩnh khác. Nếu

.c
static int count; muốn truy nhập vào các biến thành viên

ng
public: của lớp thì phải khai báo một đối tượng
A():n(0){}

co
trung gian, vì trong hàm static không có
void f(); đối tượng ngầm định *this.
static void g();

an
. . .

th
}; ng
int A:: count = 0;
void A::f(){
o
n++;
du

Hàm thành viên tĩnh là hàm


}
chung cho cả lớp không phải riêng
u

void A::g(){
cho một đối tượng nào
cu

n = 2; //???
f(x); //???
count = 2; //OK
}

Chương 4: Lớp và đối tượng 36


CuuDuongThanCong.com https://fb.com/tailieudientucntt
Kết luận về thành viên tĩnh
 Được cấp phát một vùng nhớ cố định, tồn tại ngay cả

om
khi lớp chưa có một đối tượng nào

.c
 Chung cho cả lớp, không phải của riêng mỗi đối tượng

ng
 Để biểu thị thành phần tĩnh ta dùng “tên lớp :: tên

co
thành viên tĩnh” hoặc “tên đối tượng . Tên thành viên

an
tĩnh”

th
 Được cấp phát bộ nhớ và khởi gán giá trị ban đầu bên
ng
ngoài khai báo lớp và ngoài các hàm (kể cả hàm
o

main)
du
u
cu

Chương 4: Lớp và đối tượng 37


CuuDuongThanCong.com https://fb.com/tailieudientucntt
4.10 Thành viên tĩnh(…)
 Xây dựng lớp HD (hóa đơn) gồm 2 dữ liệu là mshd

om
(mã số hóa đơn) và tienban với các hàm thực hiện
chức năng sau:

.c
– Hàm tạo hóa đơn

ng
– Hàm hủy hóa đơn

co
– Hàm sửa nội dung hóa đơn (sửa tiền bán)

an
– Hàm in ra tổng số hóa đơn và tổng số tiền bán sau các thao

th
tác tạo, hủy, sửa hóa đơn.
ng
– Viết hàm main để ứng dụng
o
du
u
cu

Chương 4: Lớp và đối tượng 38


CuuDuongThanCong.com https://fb.com/tailieudientucntt
4.11 Friend
 Vấn đề: class A{
int n;

om
public:

.c
A():n(0){}
. . .

ng
};
class B{

co
int m;

an
public:
B():m(0){}

th
ngvoid f(A a){ a.n = 5;}//???
. . .
};
o
void g(A a){
du

a.n = 10; //???


u

}
cu

 Làm thế nào để hàm phi thành viên, hàm thành viên của một
lớp khác có thể truy nhập trực tiếp vào biến thành viên của một
đối tượng?
Chương 4: Lớp và đối tượng 39
CuuDuongThanCong.com https://fb.com/tailieudientucntt
4.11 Friend(…)
 Giải pháp: khai báo bạn bè – friend

om
 Cái gì có thể là friend?

.c
– Hàm phi thành viên định nghĩa ở bên ngoài

ng
– Hàm thành viên của một lớp khác

co
– Cả lớp khác

an
class A{ class B{
int n; int m;

th
public:
ng public:
A():n(0){} B():m(0){}
friend void g(A a); void f(A a){ a.n = 5;}//OK
o
. . .
du

friend void B::f(A a);


friend class C; };
u

. . .
cu

};
void g(A a){
a.n = 10; //OK
}

Chương 4: Lớp và đối tượng 40


CuuDuongThanCong.com https://fb.com/tailieudientucntt
4.12 Nạp chồng toán tử
 Ví dụ 1: #include <iostream.h>
class Date{

om
int day, month,year;
public:

.c
Date(int d, int m, int y){
day = d; month = m; year = y;

ng
}
};

co
void main(){

an
int n = 5; Tại sao lỗi? Làm thế
cout<< n; //OK

th
nào để có thể sử
Date d(1,1,2010); dụng được như thế?
ng
cout<<d; //Lỗi
}
o
du

 Biến n thuộc kiểu cơ sở, thư viện xuất/nhập đã hỗ trợ hàm toán
u

tử xuất ra màn hình cho các biến cơ sở đó. Biến d thuộc kiểu
cu

Date do người sử dụng định nghĩa.


 Giải pháp: định nghĩa lại toán tử xuất cho lớp Date

Chương 4: Lớp và đối tượng 41


CuuDuongThanCong.com https://fb.com/tailieudientucntt
 Nạp chồng toán tử xuất cho lớp Date
#include <iostream.h>
class Date{

om
int day, month,year;
public:

.c
Date(int d=1, int m=1, int y=2010){
day = d; month = m; year = y;

ng
}

co
friend ostream& operator<<(ostream& os, const Date& d);
};

an
ostream& operator<<(ostream& os, const Date& d){

th
os<<“Ngay: ”<<d.day<<“-”<<d.month<<“-”<<d.year<<“\n”;
return os;
ng
}
o
void main(){
du

Date d(1,7,2010);
cout<<d;
u

}
cu

Chương 4: Lớp và đối tượng 42


CuuDuongThanCong.com https://fb.com/tailieudientucntt
 Ví dụ 2: Nạp chồng toán tử cho lớp số phức complex
 Vấn đề:
#include <iostream.h>
class Complex{

om
int real,imag;
public:

.c
Complex(int r, int i){

ng
real = r; imag = i;
}

co
};
void main(){

an
Complex a(1,2), b(5,6);

th
Complex c; ng
c = a + b; //Lỗi
}
o
du

 Lý do tương tự như lớp Date ở trên


u
cu

Chương 4: Lớp và đối tượng 43


CuuDuongThanCong.com https://fb.com/tailieudientucntt
 Thực hiện nạp chồng toán tử
#include <iostream.h>
class Complex{
int real,imag;

om
public:
Complex(int r = 0, int i =0): real(r),imag(i) {}

.c
Complex operator+(const Complex& b) const {

ng
Complex z(real + b.real, imag + b.imag);
return z;

co
}
Complex operator-(const Complex& b) const {

an
return Complex(real - b.real, imag - b.imag);

th
}
Complex operator*(const Complex&) const;
ng
Complex operator/(const Complex&) const;
o
Complex& operator +=(const Complex&);
du

Complex& operator -=(const Complex&);


...
u
cu

};

 Yêu cầu: sinh viên hãy thực hiện nốt các hàm còn lại
Chương 4: Lớp và đối tượng 44
CuuDuongThanCong.com https://fb.com/tailieudientucntt
 Nạp chồng các toán tử cho lớp complex sử dụng hàm bạn
#include <iostream.h>
class Complex{
int real,imag;

om
public:
Complex(int r = 0, int i =0): real(r),imag(i) {}

.c
friend Complex operator+(const Complex&, const Complex&) const;

ng
friend Complex operator-(const Complex&, const Complex&) const;
friend Complex operator*(const Complex&, const Complex&) const;

co
friend Complex operator/(const Complex&, const Complex&) const;
...

an
};

th
Complex operator+(const Complex& a,const Complex& b) const{
Complex z(a.real + b.real, a.imag + b.image);
ng
return z;
o
}
du

...
u
cu

Chương 4: Lớp và đối tượng 45


CuuDuongThanCong.com https://fb.com/tailieudientucntt
Các phép toán có thể nạp chồng
 Hầu hết các toán tử có trong C++

om
– Các toán tử số học: ++ -- + - * / % += -= ...
&& || ! & &= | |= ...

.c
– Các toán tử logic, logic bit:
– Các toán tử so sánh: == != > < >= <=

ng
– Các toán tử thao tác bit: << >> >>= <<=

co
– Các toán tử khác: [] () -> * , ...

an
 Các toán tử sau không nạp chồng được:
th ::
ng
– Toán tử truy nhập phạm vi (dấu hai chấm đúp)
.
o
– Toán tử truy nhập thành viên cấu trúc (dấu chấm)
du

– Toán tử gọi hàm thành viên qua con trỏ *->


u

– Toán tử điều kiện ? :


cu

Chương 4: Lớp và đối tượng 46


CuuDuongThanCong.com https://fb.com/tailieudientucntt
Bài tập
 1. Hãy nạp chồng các toán tử +,-,*, +=, -=, *=, ==, !=

om
sử dụng hàm thành viên, toán tử nhập/xuất cho lớp
số complex sử dụng hàm bạn

.c
 2. Bổ sung các yêu cầu sau vào lớp Array

ng
co
– Các hàm nạp chồng toán tử [] (để gán hoặc lấy giá trị của
một phần tử),

an
– Nạp chồng toán tử +, -, * hai array, hoặc array với một số

th
– Định nghĩa toán tử nhập, xuất một array
ng
– Định nghĩa toán tử gọi hàm () để lấy ra giá trị max của
o
du

mảng.
u
cu

Chương 4: Lớp và đối tượng 47


CuuDuongThanCong.com https://fb.com/tailieudientucntt

You might also like