/ 365วันแห่งโปรแกรม

[365 วันแห่งโปรแกรม #day26] Destructor

วันที่ยี่สิบหกของ ‪#‎365วันแห่งโปรแกรม‬ วันนี้เราจะมีคุยกันเรื่อง Destructor


Destructor คืออะไร?

เมื่อวานเราคุยกันเรื่อง Constructor หรือ ctor แต่วันนี้เราจะคุยกันในเรื่องของสิ่งที่ตรงข้ามกับ Constructor นั่นก็คือ Destructor หรือ dtor ซึ่งก็เป็นฟังก์ชันพิเศษเช่นเดียวกับ Constructor แต่มันจะถุกเรียกเมื่อ Object นั้นกำลังจะถูกทำลาย

Destructor มีไว้ทำอะไร?

ในภาษาที่เป็น native หรือไม่มีตัวจัดการ memory อัตโนมัตินั้นเราจำเป็นต้องเขียน Destructor เพื่อบอกว่าจะทำลาย object นี้และ release resource ต่างๆ ได้อย่างไร เพราะตัวโปรแกรมเองไม่มีทางรู้เลยว่าจะสามารถทำลาย object นั้นและส่วนอื่นที่เกี่ยวข้องได้อย่างไร แต่ในภาษาที่เป็น managed code ซึ่งมีความสามาถในการทำลาย object อัตโนมัติอยู่แล้วบางภาษาก็ยังยอมให้เราเขียน Destructor เพื่อใช้สำหรับ release resource บางอย่างที่มันจัดการเองไม่ได้ เช่น การใช้งาน native code การใช้งานฮาร์ดแวร์ เป็นต้น

เราจะสร้าง dtor ได้อย่างไร?

จริงๆ เรื่องการสร้างนั้นขึ้นอยู่กับตัวภาษาเลย เช่น ใน C++ ให้สร้างฟังก์ชันโดยตั้งชื่อเดียวกับคลาส ใส่ tilde (~) นำหน้า ไม่มี return type และไม่รับพารามิเตอร์ แต่ใน Object Pascal มี keyword destructor ให้ใช้โดยจะตั้งชื่ออะไรก็ได้ เป็นต้น ในบทความนี้เราจะอิงจาก C++ เป็นหลัก

***ตัวอย่างการสร้าง dtor ***

class Foo{
public:
	int * bar;
	Foo(){
		bar = new int[100000];
	}
	~Foo(){
		cout << "I'm dtor of Foo" << endl;
		delete []bar;
	}	
};

จากตัวอย่างคลาส Foo มี member ชื่อ bar เป็น int* เมื่อ object ของคลาส Foo ถูกสร้างขึ้น จะมีการสร้าง int[] ขนาด 100000 ตัว แล้วเอา bar ชี้ไปยัง array นั้น เมื่อ object นี้ถูกทำลาย ~Foo ซึ่งเป็น Destructor จะถูกเรียกขึ้นมา ต่อมาจะพิมพ์ข้อความ I'm dtor of Foo ออกมา แล้วทำการ delete ข้อมูลที่ bar ชี้อยู่ทิ้ง จะเห็นว่าถ้าเรามีมี Destructor เมื่อ object นี้ถูกทำลายไปแล้ว member ของมันก็จะล่องลอยอยู่ใน memory เพราะโปรแกรมไม่รู้ว่าต้องทำลาย

ใครเรียก dtor ได้บ้าง?

เราไม่สามารถเรียก dtor ขึ้นมาทำงานได้ตรงๆ แต่เราสามารถสั่ง delete object ซึ่งมันจะเรียก dtor ของ object นั้นขึ้นมาทำงาน ในภาษาโปรแกรมที่เป็น managed code ตัว garbage collector จะเป็นผู้เรียก dtor ขึ้นมาทำงาน

Overload Destructor ได้ไหม?

เนื่องจาก Destructor ไม่รับพารามิเตอร์ใดๆ ดังนั้นจึง overload ไม่ได้

Destructor ถูกสืบทอดจากแม่สู่ลูกไหม?

ไม่ครับ Destructor ไม่ถูกสืบทอดจากแม่สู่ลูกเช่นเดียวกับ Constructor และ dtor ของลูกอาจจะสามารถ/ไม่สามารถเรียก dtor ของแม่ได้ ก็แล้วแต่ภาษาโปรแกรม ถ้าภาษาไหนไม่เรียก dtor ของแม่ให้อัตโนมัติ ก็ขอให้ทำงาน dtor ขอ
ลูกให้เสร็จก่อน แล้วค่อยเรียก dtor ของแม่เอง

ตัวอย่างลำดับการเรียก dtor ใน C++

class Foo{
public:
	~Foo(){
		cout << "I'm dtor of Foo" << endl;
	}	
};

class Bar : public Foo{
public:
	~Bar(){
		cout << "I'm dtor of Bar" << endl;
	}
};

int main(){
	Bar * bar = new Bar();
	delete bar;
	return 0;
}

==output==
I'm dtor of Bar
I'm dtor of Foo

จากตัวอย่างจะเห็นว่า Bar เป็นลูกของ Foo เมื่อ object ของ Bar ถูกทำลายแล้ว dtor ของ Bar จะเริ่มทำงานก่อน หลังจากนั้นจึงเรียก dtor ของ Foo

‪#‎day26 #365วันแห่งโปรแกรม ‪#‎โครงการ365วันแห่ง‬...