Tác giả phạm hồng thái bài giảng ngôn ngữ LẬp trình c/C++



tải về 1.98 Mb.
trang47/55
Chuyển đổi dữ liệu07.07.2016
Kích1.98 Mb.
1   ...   43   44   45   46   47   48   49   50   ...   55

HÀM HỦY (Destructor)


Hàm hủy là một hàm thành viên của lớp (phương thức) có chức năng ngược với hàm tạo. Hàm hủy được gọi trước khi giải phóng (xoá bỏ) một đối tượng để thực hiện một số công việc có tính ''dọn dẹp'' trước khi đối tượng được hủy bỏ, ví dụ như giải phóng một vùng nhớ mà đối tượng đang quản lý, xoá đối tượng khỏi màn hình nếu như nó đang hiển thị, ...

Việc hủy bỏ một đối tượng thường xẩy ra trong 2 trường hợp sau:

Trong các toán tử và các hàm giải phóng bộ nhớ, như delete, free, ...

Giải phóng các biến, mảng cục bộ khi thoát khỏi hàm, phương thức.


Hàm hủy mặc định


Nếu trong lớp không định nghĩa hàm hủy, thì một hàm hủy mặc định không làm gì cả được phát sinh. Đối với nhiều lớp thì hàm hủy mặc định là đủ, và không cần đưa vào một hàm hủy mới.

Quy tắc viết hàm hủy


Mỗi lớp chỉ có một hàm hủy viết theo các quy tắc sau:

Kiểu của hàm: Hàm hủy cũng giống như hàm tạo là hàm không có kiểu, không có giá trị trả về.

Tên hàm: Tên của hàm hủy gồm một dấu ngã (đứng trước) và tên lớp:

~Tên_lớp


Đối: Hàm hủy không có đối

Ví dụ có thể xây dựng hàm hủy cho lớp DT (đa thức) như sau:

class DT

{

private:



int n; // Bac da thua

double *a; // Tro toi vung nho chua cac he so da thuc a0, a1 , ...

public:

~DT()


{

this ® n = 0;

delete this ® a;

}

...



};

Vai trò của hàm hủy trong lớp DT


Trong phần trước định nghĩa lớp DT (đa thức) khá đầy đủ gồm:

Các hàm tạo

Các toán tử nhập >>, xuất <<

Các hàm toán tử thực hiện các phép tính +, -, *, /

Tuy nhiên vẫn còn thiếu hàm hủy để giải phóng vùng nhớ mà đối tượng kiểu DT (cần hủy) đang quản lý.

Chúng ta hãy phân tích các khiếm khuyết của chương trình này:

Khi chương trình gọi tới một phương thức toán tử để thực hiện các phép tính cộng, trừ, nhân đa thức, thì một đối tượng trung gian được tạo ra. Một vùng nhớ được cấp phát và giao cho nó (đối tượng trung gian) quản lý.

Khi thực hiện xong phép tính sẽ ra khỏi phương thức. Đối tượng trung gian bị xoá, tuy nhiên chỉ vùng nhớ của các thuộc tính của đối tượng này được giải phóng. Còn vùng nhớ (chứa các hệ số của đa thức) mà đối tượng trung gian đang quản lý thì không hề bị giải phóng. Như vậy số vùng nhớ bị chiếm dụng vô ích sẽ tăng lên.

Nhược điểm trên dễ dàng khắc phục bằng cách đưa vào lớp DT hàm hủy trong mục 3 ở trên.

Ví dụ


Phần này chúng tôi trình bày một ví dụ tương đối hoàn chỉnh về lớp các hình tròn trong chế độ đồ họa. Chương trình gồm:

Lớp HT (hình tròn) với các thuộc tính:

int r; // Bán kính

int m; // Mầu hình tròn

int xhien, yhien; // Vị trí hiển thị hình tròn trên màn hình

char *pht; // Con trỏ trỏ tới vùng nhớ chứa ảnh hình tròn

int hienmh; // Trạng thái hiện (hienmh = 1), ẩn (hienmh = 0)

Các phương thức

Hàm tạo không đối thực hiện việc gán giá trị bằng 0 cho các thuộc tính của lớp. HT();

Hàm tạo có đối. HT(int n, int m1 = 15);

Thực hiện các việc:

Gán r1 cho r, m1 cho m

Cấp phát bộ nhớ cho pht

Vẽ hình tròn và lưu ảnh hình tròn vào vùng nhớ của pht

Hàm hủy: ~HT();

Thực hiện các việc:

Xoá hình tròn khỏi màn hình (nếu đang hiển thị)

Giải phóng bộ nhớ đã cấp cho pht

Phương thức: void hien(int x, int y);

Có nhiệm vụ hiển thị hình tròn tại (x, y)

Phương thức : void an()

Có nhiệm vụ làm ẩn hình tròn

Các hàm độc lập:

void ktdh(); // Khởi tạo đồ họa

void ve_bau_troi(); // Vẽ bầu trời sao

void ht_di_dong_xuong(); // Vẽ một cặp 2 hình tròn di chuyển xuống

void ht_di_dong_len(); // Vẽ một cặp 2 hình tròn di chuyển lên trên

Nội dung chương trình là tạo ra các chuyển động xuống và lên của các hình tròn.

// Lop do hoa

// Ham huy

// Trong ham huy co the goi PT khac

#include

#include

#include

#include

#include

#include

void ktdh(); // Khởi tạo đồ họa

void ve_bau_troi(); // Vẽ bầu trời sao

void ht_di_dong_xuong(); // Vẽ một cặp 2 hình tròn di chuyển xuống

void ht_di_dong_len(); // Vẽ một cặp 2 hình tròn di chuyển lên trên

int xmax, ymax;

class HT

{

private:



int r, m ;

int xhien, yhien;

char *pht;

int hienmh;

public:

HT();


HT(int n, int m1 = 15);

~HT();


void hien(int x, int y);

void an();

};
HT:: HT()

{

r = m = hienmh = 0;



xhien = yhien = 0;

pht = NULL;

}
HT::HT(int n, int m1)

{

r = n; m = m1; hienmh = 0;



xhien = yhien = 0;

if (r<0) r = 0;

if (r = = 0) pht = NULL;

else


{

int size; char *pmh;

size = imagesize(0, 0, r+r, r+r);

pmh = new char[size];

getimage(0, 0, r+r, r+r, pmh);

setcolor(m);

circle(r, r, r );

setfillstyle(1, m);

floodfill(r, r, m);

pht = new char[size];

getimage(0, 0, r+r, r+r, pht);

putimage(0, 0, pmh, COPY_PUT);

delete pmh;

pmh = NULL;

}

}
void HT::hien(int x, int y)



{

if (pmh! = NULL && !hienmh) // Chua hien

{

hienmh = 1;



xhien = x; yhien = y;

putimage(x, y, pht, XOR_PUT);

}

}
void HT::an()



{

if (hienmh) // Dang hien

{

hienmh = 0;



putimage(xhien, yhien, pht, XOR_PUT);

}

}


HT::~HT()

{

an();



if (pht! = NULL)

{

delete pht;



pht = NULL;

}

}


void ktdh()

{

int mh = 0, mode = 0;



initgraph(&mh, &mode, " ");

xmax = getmaxx();

ymax = getmaxy();

}
void ve_bau_troi()

{

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



putpixel(random(xmax), random(ymax), 1+random( 15));

}
void ht_di_dong_xuong()

{

HT h(50, 4);



HT u(60, 15);

h.hien(0, 0);

u.hien(40, 0);

for (int x = 0; x< = 340; x+ = 10)

{

h.an();


u.an();

h.hien(x, x);

delay(200);

u.hien(x+40, x);

delay(200);

}

}


void ht_di_dong_len()

{

HT h(50, 4);



HT u(60, 15);

h.hien(340, 340);

u.hien(380, 340);

for (int x = 340; x> = 0; x- = 10)

{

h.an();


u.an();

u.hien(x, x);

delay(200);

u.hien(x+40, x);

delay(200);

}

};


void main()

{

ktdh();



ve_bau_troi();

ht_di_dong_xuong();

ht_di_dong_len();

getch();

closegraph();

}

Các nhận xét:

Trong thân hàm hủy gọi tới phương thức an().

Điều gì xẩy ra khi bỏ đi hàm hủy:

Khi gọi hàm ht_di_dong_xuong() thì có 2 đối tượng kiểu HT được tạo ra. Trong thân hàm sử dụng các đối tượng này để vẽ các hình tròn di chuyển xuống. Khi thoát khỏi hàm thì 2 đối tượng (tạo ra ở trên) được giải phóng. Vùng nhớ của các thuộc tính của chúng bị thu hồi, nhưng vùng nhớ cấp phát cho thuộc tính pht chưa được giải phóng và ảnh của 2 hình tròn (ở phía dưới màn hình) vẫn không được cất đi.

Điều tương tự xẩy ra sau khi ra khỏi hàm ht_di_dong_len(): vùng nhớ cấp phát cho thuộc tính pht chưa được giải phóng và ảnh của 2 hình tròn (ở phía trên màn hình) vẫn không được thu dọn.


1   ...   43   44   45   46   47   48   49   50   ...   55


Cơ sở dữ liệu được bảo vệ bởi bản quyền ©hocday.com 2016
được sử dụng cho việc quản lý

    Quê hương