Nội dung
4.1 Khái niệm
4.2 Định nghĩa lớp
43Bế thà h ê
4
.
3
B
i
ế
n
thà
n
h
vi
ê
n
4.4 Hàm thành viên
4.5 Kiểm soát tru
y
nhậ
p
y p
4.6 Bài tập phần 1
4.7 Hàm tạo và hàm hủy
48Hàmtạobảnsao
4
.
8
Hàm
tạo
bản
sao
4.9 Hàm toán tử gán
4.10 Thành viên tĩnh
4.11 Nạp chồng toán t
ử
4.12 Khai báo friend
Chương 4: Lớp và đối tượng
© 2010 - KimThoa
2
4.1 Khái niệm
Đối tượng là gì?
— Mô hình ₫ại diện của một ₫ối tượng vật lý:
Pdll
P
erson, stu
d
ent, emp
l
oyee, emp
l
oyer
Car, bus, vehicle,…
— Đối tượng logic
Trend, report, button, window,…
Một ₫ối tượng có:
—
Các thuộctính
Các
thuộc
tính
—Trạng thái
— Hành vi
C ớ
—
C
ăn cư
ớ
c
—Ngữ nghĩa
Chương 4: Lớp và đối tượng
© 2010 - KimThoa
3
Lớp là gì?
Là sự thực thi của các ₫ối tượng có chung các thuộc
tính, hành vi, quan hệ, ngữ nghĩa.
Lớp là một kiểu dữ liệu mới có cấu trúc, trong ₫ó việc
truy nhập các biến thành viên ₫ược kiểm soát thông
qua các hàm thành viên.
qua
các
hàm
thành
viên.
Các dữ liệu của lớp ⇒ biến thành viên
Các hàm của lớ
p
⇒ hàm thành viên
p
Một biến của một lớp ⇒ một ₫ối tượng
Chương 4: Lớp và đối tượng
© 2010 - KimThoa
4
4.2 Định nghĩa lớp
Kiểu dữ liệu có cấu trúc
sruct Date{
int
day month year;
//sử dụng
void main()
{
int
day
,
month
,
year;
};
void set_date(Date& date,int d, int m, int y){
date.day = d;
date.month = m;
{
Date d;
set_date(d,32,13,2010);
add_day(d,5);
add_year(d,1);
d month = 13;
date.year = y;
}
void add_day(Date& date, int n){
date.day += n;
d
.
month = 13;
}
}
void add_month(Date& date, int n) ){
date.month += n;
}
Truy nhập biến
thành viên từ
bên ngoài
}
void add_year(Date& date, int n) ){
date.year += n;
}
Chương 4: Lớp và đối tượng
© 2010 - KimThoa
5
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
Khi có sự thay ₫ổi tên của các biến thành viên →
người sử dụng phải thay ₫ổi lại mã chương trình ứng
dụng
dụng
—Ví dụ: thay ₫ổi lại cấu trúc Date
sruct Date{
int d, m, y;
};
—Thì ₫oạn mã sau sẽ có lỗi không biên dịch
Date d;
d th 10
d
.mon
th
=
10
;
Chương 4: Lớp và đối tượng
© 2010 - KimThoa
6
Lớp hóa
Định nghĩa lớp Date
class Date{
it
d
Tên lớp
Biến thành viên
i
n
t
d
ay;
int month;
int year;
public:
void set date
(
int d
,
int m
,
int
y){
Biến
thành
viên
Kiểm soát quyền
truy nhập
_
(
,
,
y){
day = d;
month = m;
year = y;
}
int
get day() {
return
day; }
truy
nhập
Hàm thành viên
int
get
_
day() {
return
day; }
int get_month() { return month; }
int get_year() { return year; }
void add_year(int n) ){
year += n;
Hàm
thành
viên
}
};
Chương 4: Lớp và đối tượng
© 2010 - KimThoa
7
Sử dụng lớp Date
void main(){
Dt d
Đối tượng
D
a
t
e
d
;
d.set_date(1,1,2010);
d.add_year(10);
d.day = 10; //??
d.month = 10
;
//
??
Có lỗi.
day month year là
;//
d.year = 2009;//??
int i = d.day;//??
int day = d.get_day();
int month = d.get_month();
int
year = d get year();
day
,
month
,
year
là
các biến thành viên
của Date thuộc kiểu
không ₫ược phép
thậ từ bê
int
year = d
.
get
_
year();
}
t
ruy n
hậ
p
từ
bê
n
ngoài (kiểu private)
Chương 4: Lớp và đối tượng
© 2010 - KimThoa
8
Tha
y
₫ổi tên biến thành viên của lớ
p
y p
class Date{
it
d
//Sử dụng
void
main{
i
n
t
d
;
int m;
int y;
public:
void set date
(
int d
,
int m
,
int
y){
void
main{
Date d;
d.set_date(1,1,2010);
d.add_year(10);
int day = d.get_day();
_
(
_,
_,
_y){
d = _d;
m = _m;
y = _y;
}
int
get day() {
return
d; }
int month = d.get_month();
int year = d.get_year();
}
int
get
_
day() {
return
d; }
int get_month() { return m; }
int get_year() { return y; }
void add_year(int n) ){
year += n;
Có sự khác
biệt
}
};
biệt
không?
Chương 4: Lớp và đối tượng
© 2010 - KimThoa
9
4.3 Biến thành viên
Khai báo biến thành viên của lớp
class Date{
int da
y,
month
,
y
ear
;
/
/khai báo tưn
g
t
ự
như cấu trúc
y, , y ;
g ự
};
Mặc ₫ịnh các biến thành viên không truy nhập ₫ượctừ bên
Mặc
₫ịnh
các
biến
thành
viên
không
truy
nhập
₫ược
từ
bên
ngoài
Date d;
d.day = 10;; //Lỗi, vì biến thành viên day của Date thuộc kiểu private
Có thể cho phép biến thành viên truy nhập từ bên ngoài bằng
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ấudữ liệu
vậy
vì
không
còn
che
giấu
dữ
liệu
class Date{
public:
int da
y,
month
,
y
ear
;
/
/tru
y
nh
ập
₫ư
ợ
c từ bên n
g
oài
Chương 4: Lớp và đối tượng
© 2010 - KimThoa
10
y, , y ;
y ập ợ g
};
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;
public:
int
get day() {
return
day; }
Hàm thành viên
₫ể thậ biế
int
get
_
day() {
return
day; }
void set_day(int d){ day = d; }
};
₫ể
t
ruy n
hậ
p
biế
n
thành viên
Khởitạobiến thành viên thông qua hàm tạo
Khởi
tạo
biến
thành
viên
thông
qua
hàm
tạo
class Date{
int day, month,year;
p
ublic:
p
Date(int d, int m, int y){ // hàm tạo
day = d; month = m; year = y;
}
};
Chương 4: Lớp và đối tượng
© 2010 - KimThoa
11
4.4 Hàm thành viên
Khai báo và ₫ịnh nghĩa hàm thành viên
class Date{
int da
y,
month
,y
ear
;
y, ,y ;
public:
int get_day() { return day; }
void set_day(int d);
Khai báo và
₫ịnh nghĩa
Chỉ khai báo
.
.
.
};
void Date::set_day(int d){
day = d;
Chỉ
khai
báo
,
không ₫ịnh
nghĩa
Đị hhĩ bê
}
Đị
n
h
ng
hĩ
a
bê
n
ngoài phần khai
báo lớp
Để che giấucáchthựchiện hàm thành viên thường ₫ược khai
Để
che
giấu
cách
thực
hiện
,
hàm
thành
viên
thường
₫ược
khai
báo trong tập tin ₫ầu (*.h), phần ₫ịnh nghĩa ₫ược thực hiện
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ô ầ tệ ti ồ (* )
Chương 4: Lớp và đối tượng
© 2010 - KimThoa
12
khô
ng c
ầ
n
tệ
p
ti
n ngu
ồ
n
(*
.cpp
)
Khai báo hàm thành viên trong tệptin₫ầu(
*
h)
Khai
báo
hàm
thành
viên
trong
tệp
tin
₫ầu
(
.
h)
//tệp tin Date.h
class Date{
int day, month,year;
public:
int get_day();
void
set day(int d);
void
set
_
day(int d);
. . .
};
Đ hhà thà h t t t ồ (* )
Đ
ịn
h
hà
m
thà
n
h
viên
t
rong
t
ệp
t
in ngu
ồ
n
(*
.cpp
)
//tệp tin Date.cpp
void Date::set da
y(
int d
){
_
y( ){
day = d;
}
void Date::get_day(){ return day;}
Chương 4: Lớp và đối tượng
© 2010 - KimThoa
13
Con trỏ ₫ối tượng
Sử dụng con trỏ ₫ối tượng
void main{
Date d;
d.set_date(1,1,2010);
Date *
p
d = &d
;
/
/ con trỏ
p
d trỏ vào ₫ối tượn
g
d
p;
p g
pd->set_date(1,1,2010);
Date *pd1 = new Date; // cấp phát bộ nhớ, gọi hàm tạo
pd1->set_day(10);
. . .
delete pd1;
/
/ hủy bộ nhớ
Date *pd2 = new Date[5];
for(int i = 0 ;i < 5; i++)
pd2[i].set_date(1,1,2010);
. . .
delete [] pd2;
}
Chương 4: Lớp và đối tượng
© 2010 - KimThoa
14
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
thành viên của lớp và từ các bạn bè của lớp
public: các thành viên công cộng, truy nhập ₫ược ở
mọi nơi
protected
: các thành viên không truy nhập ₫ượctừ
protected
:
các
thành
viên
không
truy
nhập
₫ược
từ
bên ngoài, nhưng truy nhập ₫ược từ lớp dẫn xuất
Lớ
p
dẫn xuất
class A{
protected:
int a;
class B: public A{
public:
void
g(){
p
Lớpcơ sở
void f();
};
void
g(){
f();
}
};
Lớp
cơ
sở
Chương 4: Lớp và đối tượng
© 2010 - KimThoa
15
4.6 Bài tập
Xây dựng một lớp tên person ₫ể ₫ại diện cho một
người với các yêu cầu:
ố
—
Tên có ₫ộ dài t
ố
i ₫a 50 ký t
ự
— Ngày tháng năm sinh thuộc kiểu Date như ₫ã gợi ý trong bài
giảng.
—
Quê quán có ₫ộ dài tối ₫a 100 ký t
ự
—Hàm nhập tên, ngày sinh, quê từ bán phím
—
Hàm hiểnthị thông tin ra màn hình
Hàm
hiển
thị
thông
tin
ra
màn
hình
—Hàm lấy tên, hàm gán tên
—Hàm lấy quê quán, hàm gán quê quán
Hà lấ gà i h hà g gà i h
—
Hà
m
lấ
y n
gà
y s
i
n
h
,
hà
m
g
an n
gà
y s
i
n
h
—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
© 2010 - KimThoa
16
4.7 Hàm tạo và hàm hủy
Vấn ₫ề 1: Nghiên cứu ₫oạn mã sau
class Date{
int
day month year;
int
day
,
month
,
year;
public:
int get_day() { return day; }
void set_day(int d){ day = d; }
};
};
void main(){
Date d;
int i = d.get_date();
}
Câu hỏi
:
d.day = ?
d.month = ?
d.year = ?
}
Làm thế nào ₫ể sau khi ₫ược tạo ra, ₫ối tượng có
trạng thái ban ₫ầu theo ý muốn của người sử dụng?
Giải pháp: sử dụng hàm tạo
Chương 4: Lớp và đối tượng
© 2010 - KimThoa
17
4.7 Hàm tạo và hàm hủy (…)
V
ấn ₫ề 2: ₫ối tượng sử dụng bộ nhớ ₫ộng
class Array{
int n
;
/
/ số
p
hần tử của arra
y
;
p y
int *data; // mảng chứa giá trị các phần tử
public:
};
};
Câu hỏi: làm thế nào ₫ể cấp phát bộ nhớ và hủy bộ
nhớ cho biến thành viên data m
ộ
t cách an toàn
ộ
Giải pháp: sử dụng hàm tạo và hàm hủy.
Chương 4: Lớp và đối tượng
© 2010 - KimThoa
18
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
Hàm hủy: luôn ₫ược gọi khi ₫ối tượng bị hủy
Cú pháp:
class A{
int a, b;
bli
pu
bli
c:
A(){a = 0; b = 0;}
A(int _a){ a = _a;}
A(int _a, int _b){ a = _a; b = _b;}
A()
1
2
3
~
A()
;
};
Một lớp có thể có nhiều hàm tạo
H 1h kh ₫ố
—
H
àm tạo
1
:
h
àm tạo
kh
ông
₫ố
i
—Hàm tạo 2: hàm tạo một ₫ối
—Hàm tạo 3: hàm tạo hai ₫ối
Chương 4: Lớp và đối tượng
© 2010 - KimThoa
19
Một lớp chỉ có duy nhất một hàm hủy
Sử dụng
void main{
A a(); //gọi hàm tạo (?)
A a1(10); // gọi hàm tạo (?)
A a2(1 2);
// ihà t (?)
A a2(1
,
2);
//
gọ
i
hà
m
t
ạo
(?)
} //gọi hàm hủy cho ?
void
f(A a){
gọihàmtạo(?)
void
f(A a){
A b(0,0);
if( ){
A c;
gọi
hàm
tạo
(?)
gọi hàm tạo (?)
gọihàmhủycho?
}
}
gọi
hàm
hủy
cho
?
gọi hàm hủy cho ?
void main{
A *a = new A(10); //gọi hàm tạo (?)
. . . //sử dụng
dlt
// ihà hủ
Chương 4: Lớp và đối tượng
© 2010 - KimThoa
20
d
e
l
e
t
e a;
//
gọ
i
hà
m
hủ
y
}
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
tạo như ví dụ trên?
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
class
A{
class
A{
int a, b;
public:
A(int _a = 0, int _b = 0) { a = _a; b = _b;}
.
.
.
};
void main{
A 1
// 1 ? 1 b ?
A
a
1
;
//
a
1
.a =
?
; a
1
.
b
=
?
A a2(1); // a2.a = ?; a2.b = ?
A a3(1,2); // a3.a = ?; a3.b = ?
};
Chương 4: Lớp và đối tượng
© 2010 - KimThoa
21
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
—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 tham số hoặc kiểu của các tham số.
Nếu không ₫ịnh nghĩa hàm tạo thì compiler sẽ tự ₫ộng sinh ra
mộthàmtạovớimãthựcthilàrỗng dẫn ₫ến:
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
— Không cấp phát bộ nhớ ₫ộng cho các biến thành viên dạng mảng
₫ộng
Hà hủ là d hất
Hà
m
hủ
y
là
d
uy n
hất
Hàm hủy không bao giờ có ₫ối
Nếu không ₫ịnh nghĩa hàm hủy thì compiler cũng tự ₫ộng sinh
ra nhưng mã thựcthicủahàmhủynàylàrỗng
ra
nhưng
mã
thực
thi
của
hàm
hủy
này
là
rỗng
.
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)
ể ầ
Chương 4: Lớp và đối tượng
© 2010 - KimThoa
22
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.
Ví dụ về lớp Array
//sử dụng
//khai báo lớp Array
class Array{
int n;
int
*
data;
//sử
dụng
void main(){
Array a(5);
Array *pa = new Array(5,1);
int
data;
public:
Array(int _n = 0, int _d = 0);
~ Array();
delete pa;
}
.
.
.
};
// ₫ịnh nghĩa hàm tạo và hàm hủy
Array :: Array(int _n, int _d){
n = n;
Câu hỏi:
1. Các giá trị của mảng data của a, pa
bằng bao nhiêu?
2. Không sử dụng delete pa có ₫ược
n =
_
n;
data = new int[n];
for(int i = 0; i < n; i++)
data[i] = _d;
}
không?
3. Biến a ₫ược hủy khi nào?
}
Array ::~ Array(){
delete [] data;
}
Chương 4: Lớp và đối tượng
© 2010 - KimThoa
23
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
(xem các ví dụ sau)
Cú pháp chuẩn:
class A{
int a, b;
public
:
Sao chép tham
số từ a1, a1
public
:
A(const A& a1);
. . .
};
//₫ịnh nghĩahàmsaochép
không bị thay
₫ổi do vô tình
//₫ịnh
nghĩa
hàm
sao
chép
A::A(const A& a1){
a = a1.a;
b = a1.b;
}
}
//sử dụng
void main(){
A a;
A a1
(
a
);
Gọi hàm tạo
bản sao
Chương 4: Lớp và đối tượng
© 2010 - KimThoa
24
();
}
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);
X x3 = x1;
X x4
=
X(x1);
X x4 X(x1);
—
Khi truyền tham số qua giá trị cho một hàm
void f(X x) { }
void main(){
ở đây có sự gọi hàm tạo bản
sao để sao chép nội dung của
X a;
f(a);
}
sao
để
sao
chép
nội
dung
của
a để truyền vào cho tham biến
hình thức x của hàm f
-Khi một hàm trả về một ₫ối tượng
X f() {
X x1;
. . .
// thựchiệnthuậttoán
. . .
//
thực
hiện
thuật
toán
return x1;
}
void main(){
X x
=
f();
ở đây có sự gọi hàm tạo bản sao để
sao chép nội dung của biến tạm x1
sang cho biến x sau khi thực hiện
xong lệnh return trong hàm f
Chương 4: Lớp và đối tượng
© 2010 - KimThoa
25
X x f();
. . .
}
xong
lệnh
return
trong
hàm
f
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
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ì
khôn
g
cần ₫ịnh n
g
hĩa hàm tạo bản sao
g g
Khi có tham biến ₫ược cấp phát ₫ộng thì bắt buộc
₫ịnh nghĩa lại hàm tạo bản sao.
//khai báo lớp Array không có hàm tạo bản sao
class Array{
int
n;
int
n;
int *data;
public:
Array(int _n = 0; int _d = 0) { }
~
Array(){ }
Array(){ }
void set_data(int i, int d){
if((i>=0) && (i<n))
data[i] = d;
};
Chương 4: Lớp và đối tượng
© 2010 - KimThoa
26
};