Search…

Sự Ra Đời Của Phương Thức Khởi Tạo (Constructor), Phương Thức Hủy (Destructor) Trong Một Class - C++

21/08/20203 min read
Tìm hiểu về phương thức khởi tạo (Constructor) và phương thức hủy (Destructor), cách sử dụng hiệu quả thông qua các ví dụ.

Constructor và Destructor là gì?

Phương thức khởi tạo (Constructor) hay phương thức hủy (Destructor) là 2 trong số các phương thức mang lại sự tiện lợi khi lập trình với class.

  • Constructor: phương thức tự động được gọi sau khi đối tượng được tạo xong.
  • Destructor: phương thức tự động được gọi trước khi đối tượng tiến hành hủy.

Cách sử dụng Constructor và Destructor trong C++

  • Constructor: hàm được định nghĩa bằng cách đặt tên trùng với tên class và không có kiểu trả về.
  • Destructor: hàm được định nghĩa bằng cách đặt trùng với tên class và thêm ký tự ~ vào phía trước.
#include <iostream>

class Node
{
public:
	// Constructor
	Node()
	{
		std::cout << "Constructor Called";
	}
	
	// Destructor
	~Node()
	{
		std::cout << "Destructor Called";
	}
}

int main()
{
	Node node;

	return 0;
}

Sau dòng Node node;

  • Đối tượng node được tạo ra.
  • Sau đó Node() tự động được gọi.
  • Đến giai đoạn kết thúc hàm main(), đối tượng node sẽ được thu hồi nhưng trước đó sẽ tự động gọi ~Node().

Các trường hợp sử dụng Constructor tăng tính hiệu quả

Constructor và Destructor không bắt buộc phải định nghĩa. Trong những ngữ cảnh không cần thiết thì không cần định nghĩa 2 phương thức này.

Câu chuyện của Constructor

Giả sử Node là 1 phần tử trong danh sách liên kết, nghĩa là next sẽ lưu giữ vị trí của node kế tiếp hoặc đánh dấu là node cuối cùng (nullptr).

#include <iostream>

class Node
{
private:
    Node *next;
public:
	void init()
	{
		this->next = nullptr;
	}
}

int main()
{
	Node node;
	node.init();

	return 0;
}

Dòng node.init() được gọi sau khi node được tạo ra, để đảm bảo next luôn là node cuối cùng (khi chưa thêm vào danh sách).

Điều này bất tiện vì node.init() không đáng tin cậy vì có lúc quên gọi, mặc dù điều này là 1 mong muốn mặc định khi 1 node ra đời thì next phải là nulltpr. Trong trường hợp này, constructor sẽ thể hiện được sức mạnh của nó.

#include <iostream>

class Node
{
private:
    Node *next;
public:
	Node()
	{
		this->next = nullptr;
	}
}

int main()
{
	Node node;

	return 0;
}

Như vậy không cần phải luôn tự nhắc bản thân gán nullptr sau khi node được tạo ra.

Câu chuyện của Destructor

Với ví dụ về Node trong danh sách liên kết, thấy được tính hiệu quả của Constructor, nhưng về Destructor không mang nhiều tính hữu ích rõ ràng, vì trong thực tế node có thể được tái sử dụng, bị hủy ngay lập tức, bị thu hồi 1 cách chủ động, hoặc trở thành 1 node zombie, nên ở phần Destructor sẽ được sử dụng 1 ví dụ khác.

Ví dụ tạo 1 kiểu dữ liệu mới, lớp Integer (kiểu số nguyên) để thấy được tính hữu ích của Destructor.

  • Lớp Integer này tạo ra 1 kiểu dữ liệu mới mà tại thời điểm thực thi, 4 byte dữ liệu của kiểu integer được lưu ngẫu nhiên trên các vùng nhớ để tránh các trường hợp rà soát dữ liệu trên bộ nhớ.
  • Lớp Integer này mặc dù được viết dưới dạng hướng đối tượng, nhưng để sử dụng cho tiện lợi, cần viết các phương thức sao cho nó được thao tác thoải mái như đang làm việc với kiểu int.
    • Nên cần thêm các operator overload.
    • Nên phải được hủy 1 cách tự nhiên khi ra khỏi tầm vực thay vì phải tự gọi phương thức destroy, đây chính là điểm hữu dụng của destructor.
using BYTE = unsigned char;

class Integer
{
private:
    BYTE* byte[4];
public:
    Integer(int value)
    {
        BYTE* temp = reinterpret_cast<BYTE*>(&value);

        for (int i = 0; i < 4; i++)
        {
            byte[i] = new BYTE;
            *byte[i] = temp[i];
        }
    }

    ~Integer()
    {
        for (int i = 0; i < 4; i++)
        {
            if (byte[i] != nullptr)
                delete byte[i];
        }
    }
};

int main()
{
    Integer i(1);
    Integer i(2);

    // Integer i3 = i1 + i2;

    return 0;
}
IO Stream

IO Stream Co., Ltd

30 Trinh Dinh Thao, Hoa Thanh ward, Tan Phu district, Ho Chi Minh city, Vietnam
+84 28 22 00 11 12
developer@iostream.co

383/1 Quang Trung, ward 10, Go Vap district, Ho Chi Minh city
Business license number: 0311563559 issued by the Department of Planning and Investment of Ho Chi Minh City on February 23, 2012

©IO Stream, 2013 - 2024