ySử dụng được các lớp theo nghĩa hướng về với đối OOP-CHƯƠNG 4-PHƯƠNG THỨC TỰ THỰC HIỆN tượng tạo đối tượng, thì đối tượng tự giải quyết vấn đề nào đó GV: Võ Hồng Bảo Châu 3 NỘI DUNG CHI
Trang 1CHƯƠNG 4 PHƯƠNG THỨC TỰ THỰC HIỆN
OOP-CHƯƠNG 4-PHƯƠNG THỨC TỰ THỰC HIỆN GV: Võ Hồng Bảo Châu
2
MỤC TIÊU
yHiểu rõ phương thức thiết lập, huỷ bỏ và thiết lập sao chép
yXây dựng lớp có các phương thức tự động thực hiện
ySử dụng được các lớp theo nghĩa hướng về với đối
OOP-CHƯƠNG 4-PHƯƠNG THỨC TỰ THỰC HIỆN
tượng (tạo đối tượng, thì đối tượng tự giải quyết vấn
đề nào đó)
GV: Võ Hồng Bảo Châu
3
NỘI DUNG CHI TIẾT
4
Phương thức tự động thực hiện
yTrong C++ có 2 phương thức thuộc loại này:
{ Phương thức thiết lập (constructor)
{ Phương thức hủy bỏ (destructor)
yChương trình mang đúng nghĩa hướng về với đối t
tượng:
{ Khi tạo ra đối tượng, một số hành vi sẽ thực thi vào thời điểm đó.
Trang 2Khi đó,
yĐối tượng không chỉ đơn thuần là dữ liệu có cấu trúc
đã được tạo ra
yMà còn,
{ Mang tính hành động: một hoặc một số hành vi nào đó của nó
đ c thi hành
OOP-CHƯƠNG 4-PHƯƠNG THỨC TỰ THỰC HIỆN
được thi hành.
yVà ngược lại,
{ Khi đối tượng mất đi, sẽ có một số hành động được thực thi.
GV: Võ Hồng Bảo Châu
6
Phương thức thiết lập
yĐược thực hiện một cách tự động ngay sau khi đối tượng được tạo ra
yNhằm thực hiện một số công việc ban đầu như:
{ Tạo ra vùng bộ nhớ { Sao chép, khởi tạo giá trị ban đầu cho dữ liệu
OOP-CHƯƠNG 4-PHƯƠNG THỨC TỰ THỰC HIỆN
{ Sao chép, khởi tạo giá trị ban đầu cho dữ liệu { v.v
yLớp trong C++ có thểcó hoặc không cóphương thức thiết lập
yKhi không có, một số hành động sau được thực hiện:
{ Dành bộ nhớ cho các dữ liệu { Khởi tạo giá trị không cho tất cả các byte của dữ liệu
GV: Võ Hồng Bảo Châu
7
yTrong C++, phương thức thiết lập có tên trùng với tên
của lớp, không có kiểu trả về Chẳng hạn,
phương thức thiết lập,
tên giống tên lớp Tạo ra đối tượng p
Tự động gọi phương thức thiết lập
8 8
yKhi tạo đối tượng, nếu không chỉ định thêm bất kỳ điều gì Chẳng hạn,
STACK S;
yThì phương thức thiết lập chuẩn được gọi thực hiện một cách tự động
Không có phương thức thiết lập Không báo lỗi vì có pthức thiết lập chuẩn được gọi tự động
Trang 3Vậy, thế nào là constructor chuẩn
yPhương thức thiết lập chuẩn là phương thức thiết lập
không có tham số
yHoặc phương thức thiết lập với tất cả các tham số
được gán giá trị đầu Chẳng hạn,
OOP-CHƯƠNG 4-PHƯƠNG THỨC TỰ THỰC HIỆN
STACK( unsigned int = 1237 );
VECTOR( int = 2;double = 3.5 );
Phương thức thiết lập có thuộc
tính truy cập là public
GV: Võ Hồng Bảo Châu
10
class Point {
int xVal, yVal;
public:
Point () // Hàm thiết lập chuẩn
{ xVal = 0; yVal = 0; }
Point (int x, int y) {
xVal = x; yVal = y;
yMột lớp có thể có nhiều phương thức thiết lập
yChúng khác nhau qua danh sách tham số
OOP-CHƯƠNG 4-PHƯƠNG THỨC TỰ THỰC HIỆN
y y }
void OffsetPt (int , int ); … };
void main(){
Point p1;
Point p2(10,20);
}
yĐây chính là khả năng định nghĩa chồng lên nhau (overloading) của các hành vi trong lớp
GV: Võ Hồng Bảo Châu
Gợi ý khi xây dựng constructor
yViệc thường làm là gán trị cho các thành phần dữ liệu của đối tượng
ySố constructor có trong một lớp thường là những dạng dữ liệu của đối tượng mà ta muốn có ngay lúc
b đầ ban đầu
Trang 4Phương thức hủy bỏ
yPhương thức hủy bỏ (destructor) được thực hiện trước khi
đối tượng bị mất đi (trước khi vùng bộ nhớ dành cho đối
tượng bị thu hồi)
ySử dụng mang tính dọn dẹp, hoặc thông báo về sự kết
thúc hoạt động
yTrong C++ phương thức hủy bỏ được viết như sau:
OOP-CHƯƠNG 4-PHƯƠNG THỨC TỰ THỰC HIỆN
yTrong C++, phương thức hủy bỏ được viết như sau:
~ClassName()
yMột lớp chỉ có 1 phương thức hủy bỏ
yTrong các thành phần của lớp, thành phần nào được khai
báo trước, phương thức thiết lập sẽ thực hiện trước
yTrong các thành phần của lớp, thành phần nào được khai
báo trước, phương thức hủy bỏ sẽ thực hiện sau
GV: Võ Hồng Bảo Châu
14
Tổng cộng
có bao nhiêu l nhiêu lầần n
OOP-CHƯƠNG 4-PHƯƠNG THỨC TỰ THỰC HIỆN
nhiêu l nhiêu lầần n hàm hủy được gọi ?
GV: Võ Hồng Bảo Châu
15
BÀI TẬP LÀM TẠI LỚP
yXây dựng lớp PhanSo gồm 2 thành phần tử số và mẫu số
Viết hàm thiết lập (có và không có tham số) và hàm hủy
bỏ đáp ứng yêu cầu của hàm main sau:
void main()
{
PhanSo a;
PhanSo a;
PhanSo b(1,2),c(3,4);
getch();
}
Cho biết hàm thiết lập, hủy bỏ được gọi bao nhiêu lần và thứ
tự thiết lập, hủy bỏ các đối tượng
Thời gian làm bài: 5 phút
16
yXây dựng lớp NhietDo gồm 2 thành phần giá trị (số thực) và loại (ký tự, C hoặc F) Viết các hàm cần thiết
để hàm main sau đây chạy đúng void main()
{ { NhietDo a(20,’C’),b(135,’F’);
NhietDo c,d;
} Cho biết thứ tự thực hiện của hàm thiết lập và hủy bỏ Thời gian làm bài: 5 phút
Trang 517 17
Phương thức thiết lập tạo bản sao
yCòn gọi là Copy Constructor
yMục tiêu
{ Nhằm để tạo ra bản sao của đối tượng, trong đó quản lý chặt chẽ
những gì được làm, được sao chép
{ Quản lý bản sao của đối tượng được tạo ra
OOP-CHƯƠNG 4-PHƯƠNG THỨC TỰ THỰC HIỆN
{ Quản lý bản sao của đối tượng được tạo ra
Đây là phương thức có trong C++
GV: Võ Hồng Bảo Châu
18
Trường hợp tạo bản sao
yKhi cần tạo bản sao, có thể viết như sau:
EXAMPLE A;
EXAMPLE B = A;
yKhi đó B là bản sao của đối tượng A, những gì được
OOP-CHƯƠNG 4-PHƯƠNG THỨC TỰ THỰC HIỆN
làm khi sao chép sẽ được quy định trong phương thức
thiết lập tạo bản sao của lớp EXAMPLE.
GV: Võ Hồng Bảo Châu
19
yVới cách viết EXAMPLE B = A, chẳng qua để dễ sử
dụng – đồng nhất việc gán với việc sao chép Thực
chất, câu lệnh này là:
EXAMPLE B(A)
yCũng cần lưu ý thêm câu lệnh gán chỉ gán giá trị
yCũng cần lưu ý thêm, câu lệnh gán chỉ gán giá trị
B = A;
yHoàn toàn khác câu lệnh – tạo đối tượng
EXAMPLE B = A;
20 20
Cách thức viết copy constructor
yPhương thức thiết lập tạo bản sao là một phương thức như mọi phương thức khác, nên chứa các câu lệnh cần thực hiện
yTuy nhiên, do đặc thù là được điều khiển một cách tự
động, nên tên gọi và tham số được quy ước:
ClassName( ClassName& )
Trang 6yTrong lớp này, khi một bảo sao của đối tượng (được
truyền qua tham số) được tạo ra, chỉ thành phần dữ
liệu n của lớp mới có giá trị giống giá trị n của bản gốc
yNói cách khác, nó chỉ "bắt chước" thành phần dữ liệu
OOP-CHƯƠNG 4-PHƯƠNG THỨC TỰ THỰC HIỆN
n.
GV: Võ Hồng Bảo Châu
22 22
Ví dụ
OOP-CHƯƠNG 4-PHƯƠNG THỨC TỰ THỰC HIỆN GV: Võ Hồng Bảo Châu
23 23
yMột lớp luôn luôn có 1 phương thức thiết lập tạo bản
sao
yPhương thức đó có thể hiện thực hay không hiện thực
yKhi không hiện thực, một phương thức tạo bản sao
chuẩn sẽ âm thầm tồn tại
Nguy hiểm trong lập trình là khi mọi thứ
diễn ra một cách âm thầm, người lập trình
không hay biết
24
Không có hàm thiết lập sao chép, hàm thiết lập sao chép chuẩn sẽ được gọi
Trang 725 25
yPhương thức thiết lập tạo bản sao được thi hành khi:
{Khởi tạo đối tượng bởi đối tượng đã có
{Tham số thực được truyền cho tham số giá trị của một
phương thức nào đó
OOP-CHƯƠNG 4-PHƯƠNG THỨC TỰ THỰC HIỆN
{Phương thức trả đối tượng của lớp trở về thông qua
tên gọi (return Obj)
GV: Võ Hồng Bảo Châu
26
OOP-CHƯƠNG 4-PHƯƠNG THỨC TỰ THỰC HIỆN
Hàm thiết lập sao chép được gọi khi tham số thực được truyền cho tham số giá trị của một phương
thức nào đó
GV: Võ Hồng Bảo Châu
27
Hàm thiết lập tạo bản sao được gọi khi phương thức
trả đối tượng của lớp trở về thông qua tên gọi
(return Obj)
28
THÌ COPY CONSTRUCTOR CHUẨN SẼ ĐƯỢC GỌI
KHÔNG CÓ CŨNG ĐƯỢC
??
Trang 829 29
Lưu ý
yVấn đề chỉ nảy sinh phức tạp khi việc cấp phát và thu
hồi bộ nhớ được thực thi
yBởi khi đó, có thể vô tình thu hồi vùng bộ nhớ đang
được sử dụng bởi một bản sao nào đó
OOP-CHƯƠNG 4-PHƯƠNG THỨC TỰ THỰC HIỆN GV: Võ Hồng Bảo Châu
30 30
Xét lớp VECTOR như sau
class VECTOR{
int size;
double *data;
public:
VECTOR( int = 2 );
OOP-CHƯƠNG 4-PHƯƠNG THỨC TỰ THỰC HIỆN
VECTOR( int 2 );
VECTOR( VECTOR& );//copy constructor
~VECTOR();
void setData( double = 0.0 );
void outData();
}
GV: Võ Hồng Bảo Châu
31
yNếu không có phương thức thiết lập tạo bản sao, hoặc
viết không đúng yêu cầu Một vùng bộ nhớ bị thu hồi
hai lần
yBởi thực chất có 2 đối tượng, nhưng trong trường hợp
này cả hai đối tượng này có chung một vùng bộ nhớ
32 32
Chúng ta xem xét cụ thể hơn
VECTOR::VECTOR( int n ){
size = n;
data = new double[size];
setData();
cout << "Object at " << data << endl;
cout << Object at << data << endl;
} VECTOR::~VECTOR(){
cout << "Memory location << data
<< "has been destroyed\n";
delete []data;
}
Trang 933 33 VECTOR::VECTOR( VECTOR& V ){
size = V.size;
data = new double[size];
cout<<“copy constructor”<<endl;
cout << "Object at " << data << endl;
setData();
}
OOP-CHƯƠNG 4-PHƯƠNG THỨC TỰ THỰC HIỆN
void VECTOR::setData( double a ){
for ( int i = 0; i < size; i++ )
data[i] = a;
}
void VECTOR::outData(){
for ( int i = 0; i < size; i++ )
cout << data[i] << ", ";
cout << endl;
}
GV: Võ Hồng Bảo Châu
34 34
Khởi tạo đối tượng
void main(){
VECTOR u;
u.outData();
VECTOR v = u;
Object at 0x8f7d128e
0, 0, copy constructor
Object at 0x8f7d12a2
0, 0,
Memory location0x8f7d12a2has been destroyed Memory location0x8f7d128ehas been destroyed
Có phương thức copy constructor Hai đối tượng có
2 vùng nhớ
OOP-CHƯƠNG 4-PHƯƠNG THỨC TỰ THỰC HIỆN
; v.outData();
}
Memory location0x8f7d128ehas been destroyed
Object at 0x8f75126e
0, 0,
0, 0,
Memory location0x8f75126ehas been destroyed Memory location0x8f75126ehas been destroyed
Không có phương thức copy constructor Hai đối tượng có 1 vùng nhớ 1 vùng nhớ bị thu hồi 2 lần.
GV: Võ Hồng Bảo Châu
35
Lưu ý
yVới phương thức thiết lập của lớp VECTOR như trên,
chúng ta có thể viết
VECTOR u = 5;
yTrường hợp này đồng nghĩa với
VECTOR u(5);
yNên phương thức thiết lập tạo bản sao không được gọi
đến
Tham số giá trị
yKhi truyền tham số thực cho tham số giá trị của một phương thức, thì phương thức thiết lập tạo bản sao sẽ được gọi đến
yChẳng hạn, để tính tích vô hướng của hai vector
∑
=
= n
i i
iv u v
u
1
) , (
Trang 10double VECTOR::scalar(VECTOR v){
double t = 0.0;
for(int i = 0; i<size; i++ )
t += data[i]*v.data[i];
OOP-CHƯƠNG 4-PHƯƠNG THỨC TỰ THỰC HIỆN
return t;
}
GV: Võ Hồng Bảo Châu
38 38
yChương trình gọi có thể viết VECTOR u(5), v(5);
u.setData(2.0);
OOP-CHƯƠNG 4-PHƯƠNG THỨC TỰ THỰC HIỆN
v.setData(3.0);
cout << "(u,v) = "
<< u.scalar(v) << endl;
GV: Võ Hồng Bảo Châu
39 39
yĐể kiểm tra sự hoạt động của trường hợp này, chúng
ta không hiện thực phương thức thiết lập tạo bản sao
yMột bản sao của v được tạo ra; khi hàm scalar()
thực hiện xong, địa chỉ data của bản sao này được
th hồi (d ó h thứ hủ bỏ)
thu hồi (do có phương thức hủy bỏ)
40 40
yĐến lượt kết thúc, một lần nữa địa chỉ data của v lại
bị thu hồi, trong khi đó 2 địa chỉ này lại giống nhau –
do không có phương thức thiết lập tạo bản sao
Để khắc phục tình trạng này, sử dụng tham
số dạng tham chiếu:
scalar(VECTOR& v)
Trang 11Hàm trả về đối tượng
yPhương thức thiết lập tạo bản sao sẽ được gọi để tạo ra
bản sao khi hàm trả về một đối tượng của lớp
OOP-CHƯƠNG 4-PHƯƠNG THỨC TỰ THỰC HIỆN GV: Võ Hồng Bảo Châu
42 42
yChẳng hạn, tổng của 2 vector:
VECTOR VECTOR::add(VECTOR v){
VECTOR t(size);
OOP-CHƯƠNG 4-PHƯƠNG THỨC TỰ THỰC HIỆN
for(int i=0; i<size; i++ ) t.data[i] = data[i] + v.data[i];
return t;
}
GV: Võ Hồng Bảo Châu
43 43
yChương trình gọi có thể viết
void main(){
VECTOR u(3), v(3);
u.setData(1.0);( );
v.setData(4.0);
(u.add(v)).outData();
}
Chúng ta thử bỏ copy constructor trong
lớp VECTOR này để theo dõi kết quá
44 44
yChúng ta cũng có thể lưu lại kết quả tổng 2 vector bằng cách bổ sung
VECTOR t = u.add(v);
t.outData();
yKết quả hoàn toàn tương tự
Trang 1245 45
Phép toán gán
yNhưng khi dùng phép toán gán
VECTOR t(3);
t = u.add(v);
t.outData();
OOP-CHƯƠNG 4-PHƯƠNG THỨC TỰ THỰC HIỆN
yKết quả không như mong đợi
GV: Võ Hồng Bảo Châu
46 46
Lý do
yPhép toán gán chuẩn sẽ gán từng byte của đối tượng này cho đối tượng kia, khi đó các biến liên quan đến địa chỉ cũng hoàn toàn giống nhau
OOP-CHƯƠNG 4-PHƯƠNG THỨC TỰ THỰC HIỆN
Phương thức thiết lập tạo bản sao sẽ tạo
ra một đối tượng mới; còn phép toán gán chỉ làm thay đổi giá trị của đối tượng
GV: Võ Hồng Bảo Châu
47
yCó thể bổ sung thêm hàm assign() để gán giá trị:
VECTOR VECTOR::assign(VECTOR v){
size = v.size();
for(int i = 0; i < size; i++ )( ; ; )
data[i] = v.data[i];
return *this;
}
48
TỰ KẾT LUẬN
COPY CONSTRUCTOR TƯỜNG MINH?
Trang 13TÓM TẮT
LẬP, HỦY BỎ, SAO CHÉP
OOP-CHƯƠNG 4-PHƯƠNG THỨC TỰ THỰC HIỆN
CONSTRUCTOR?
GV: Võ Hồng Bảo Châu
50
OOP-CHƯƠNG 4-PHƯƠNG THỨC TỰ THỰC HIỆN
THANK YOU
GV: Võ Hồng Bảo Châu