C++ ความแตกต่างพร้อมตัวอย่าง

⚡ สรุปอย่างชาญฉลาด

ความแตกต่างใน C++ อนุญาตให้ฟังก์ชันสมาชิกเดียวมีได้หลายรูปแบบ โดยมีพฤติกรรมแตกต่างกันไปขึ้นอยู่กับวัตถุที่เรียกใช้ ฟังก์ชันนี้สร้างขึ้นบนพื้นฐานของการสืบทอด และปรากฏในสองรูปแบบ ซึ่งจะถูกตัดสินในระหว่างการคอมไพล์หรือระหว่างการทำงาน

  • 🔷 ความหมาย: Polymorphism หมายถึง “หลายรูปแบบ” ที่อนุญาตให้ฟังก์ชันสมาชิกหนึ่งฟังก์ชันทำงานแตกต่างกันไปตามวัตถุที่เรียกใช้
  • 🧭 สองประเภท: C++ รองรับการทำงานแบบโพลีมอร์ฟิซึมทั้งในเวลาคอมไพล์ (แบบคงที่) และในเวลารันไทม์ (แบบไดนามิก)
  • 🧩 เวลาในการคอมไพล์: การโอเวอร์โหลดฟังก์ชันและการโอเวอร์โหลดตัวดำเนินการจะเลือกฟังก์ชันที่ถูกต้องในระหว่างการคอมไพล์
  • 🔁 เวลาทำงาน: การเขียนทับฟังก์ชันและการใช้ฟังก์ชันเสมือนจะช่วยแก้ไขการเรียกใช้งานในระหว่างที่โปรแกรมกำลังทำงาน
  • ⚙️ ฟังก์ชันเสมือน: คีย์เวิร์ด virtual ในคลาสพื้นฐานช่วยให้สามารถผูกข้อมูลแบบล่าช้าผ่านตัวชี้ไปยังคลาสพื้นฐานได้
  • 🤖 ความช่วยเหลือจากเอไอ: GitHub Copilot และเครื่องมือช่วยอื่นๆ ที่คล้ายกัน จะสร้างฟังก์ชันที่มีการโอเวอร์โหลด ฟังก์ชันที่ถูกแทนที่ และฟังก์ชันเสมือน จากข้อความแสดงความคิดเห็นสั้นๆ

C++ ความหลากหลาย

Polymorphism คืออะไร C++?

In C++โพลีมอร์ฟิซึมทำให้ฟังก์ชันสมาชิกทำงานแตกต่างกันไปตามวัตถุที่เรียกใช้ โพลีมอร์ฟิซึมเป็นคำภาษากรีกที่หมายถึงการมีหลายรูปแบบ เกิดขึ้นเมื่อมีลำดับชั้นของ ชั้นเรียน มีความสัมพันธ์ทางกรรมพันธุ์

ตัวอย่างเช่น สมมติว่าเรามีฟังก์ชัน makeSound() เมื่อแมวเรียกใช้ฟังก์ชันนี้ มันจะส่งเสียงร้องเหมียว เมื่อวัวเรียกใช้ฟังก์ชันเดียวกัน มันจะส่งเสียงวัว

ความแตกต่างใน C++ ตัวอย่าง makeSound

แม้ว่าเราจะมีฟังก์ชันเดียว แต่ก็มีพฤติกรรมที่แตกต่างกันภายใต้สถานการณ์ที่ต่างกัน ฟังก์ชันมีหลายรูปแบบ ดังนั้นเราจึงประสบความสำเร็จในความหลากหลาย

เมื่อมีแนวคิดหลักที่ชัดเจนแล้ว C++ จัดพฤติกรรมนี้ออกเป็นสองประเภทที่แตกต่างกัน

ประเภทของความหลากหลาย

C++ รองรับความหลากหลายสองประเภท:

  • พหุสัณฐานเวลาคอมไพล์ และ
  • ความหลากหลายแบบรันไทม์

ประเภทของโพลีมอร์ฟิซึมใน C++

หมวดหมู่แรกจะจัดการกับการเรียกใช้ฟังก์ชันทั้งหมดก่อนที่โปรแกรมจะเริ่มทำงาน

ความหลากหลายของเวลาคอมไพล์

คุณเรียกใช้ฟังก์ชันโอเวอร์โหลดโดยการจับคู่จำนวนและประเภทของอาร์กิวเมนต์ ข้อมูลจะปรากฏในระหว่างเวลาคอมไพล์ ซึ่งหมายความว่า C++ คอมไพเลอร์จะเลือกฟังก์ชันที่ถูกต้องในเวลาคอมไพล์

ความแปรปรวนร่วมในเวลาคอมไพล์ทำได้โดยการโอเวอร์โหลดฟังก์ชันและการโอเวอร์โหลดตัวดำเนินการ

ฟังก์ชั่นโอเวอร์โหลด

ฟังก์ชั่นโอเวอร์โหลดเกิดขึ้นเมื่อเรามีฟังก์ชั่นมากมายที่มีชื่อคล้ายกันแต่มีข้อโต้แย้งต่างกัน อาร์กิวเมนต์อาจแตกต่างกันในแง่ของจำนวนหรือประเภท

1 ตัวอย่าง

#include <iostream> 
using namespace std;

void test(int i) {
	cout << " The int is " << i << endl;
}
void test(double  f) {
	cout << " The float is " << f << endl;
}
void test(char const *ch) {
	cout << " The char* is " << ch << endl;
}

int main() {
	test(5);
	test(5.5);
	test("five");
	return 0;
}

Output:

C++ ตัวอย่างที่ 1 ของผลลัพธ์การโอเวอร์โหลดฟังก์ชัน

นี่คือภาพหน้าจอของรหัส:

C++ ตัวอย่างโค้ดการโอเวอร์โหลดฟังก์ชัน 1

Code คำอธิบาย:

  1. รวมไฟล์ส่วนหัว iostream ลงในโค้ดของเรา เราจะสามารถใช้ฟังก์ชั่นของมันได้
  2. รวมเนมสเปซมาตรฐานไว้ในโค้ดของเรา เราจะสามารถใช้คลาสของมันได้โดยไม่ต้องเรียกมัน
  3. สร้างฟังก์ชันชื่อ test ที่รับพารามิเตอร์จำนวนเต็ม i { เป็นจุดเริ่มต้นของการทดสอบเนื้อความของฟังก์ชัน
  4. คำสั่งที่จะดำเนินการหากมีการเรียกใช้/เรียกใช้การทดสอบฟังก์ชันข้างต้น
  5. ส่วนท้ายของการทดสอบการทำงานข้างต้น
  6. สร้างฟังก์ชันชื่อ test ที่ใช้พารามิเตอร์ float f { เป็นจุดเริ่มต้นของการทดสอบเนื้อความของฟังก์ชัน
  7. คำสั่งที่จะดำเนินการหากมีการเรียกใช้/เรียกใช้การทดสอบฟังก์ชันข้างต้น
  8. ส่วนท้ายของการทดสอบการทำงานข้างต้น
  9. สร้างฟังก์ชันชื่อ test ที่รับพารามิเตอร์อักขระ ch { เป็นจุดเริ่มต้นของการทดสอบเนื้อความของฟังก์ชัน
  10. คำสั่งที่จะดำเนินการหากมีการเรียกใช้/เรียกใช้การทดสอบฟังก์ชันข้างต้น
  11. ส่วนท้ายของการทดสอบการทำงานข้างต้น
  12. เรียกใช้ฟังก์ชัน main() { เป็นจุดเริ่มต้นของเนื้อความของฟังก์ชัน
  13. เรียกใช้การทดสอบฟังก์ชันและส่ง 5 ให้เป็นค่าของอาร์กิวเมนต์ ซึ่งจะเรียกใช้ฟังก์ชันทดสอบที่ยอมรับอาร์กิวเมนต์จำนวนเต็ม ซึ่งก็คือฟังก์ชันทดสอบแรก
  14. เรียกใช้การทดสอบฟังก์ชันและส่ง 5.5 ให้เป็นค่าของอาร์กิวเมนต์ สิ่งนี้จะเรียกใช้ฟังก์ชันทดสอบที่ยอมรับอาร์กิวเมนต์ float นั่นคือฟังก์ชันทดสอบที่สอง
  15. เรียกใช้การทดสอบฟังก์ชันและส่งค่าห้าให้เป็นค่าของอาร์กิวเมนต์ ซึ่งจะเรียกใช้ฟังก์ชันทดสอบที่ยอมรับอาร์กิวเมนต์อักขระ ซึ่งก็คือฟังก์ชันทดสอบตัวที่สาม
  16. โปรแกรมจะต้องส่งคืนค่าหากทำงานได้สำเร็จ
  17. ส่วนท้ายของฟังก์ชัน main()

เรามีฟังก์ชันสามฟังก์ชันที่มีชื่อเดียวกันแต่อาร์กิวเมนต์ต่างกัน เราบรรลุถึงความหลากหลายแล้ว

Operaทอร์โอเวอร์โหลด

In Operator Overloading เราให้คำจำกัดความใหม่แก่ C++ ผู้ประกอบการนอกจากนี้ยังเปลี่ยนวิธีการทำงานของตัวดำเนินการด้วย ตัวอย่างเช่น เราสามารถกำหนดตัวดำเนินการ + เพื่อเชื่อมต่อสตริงสองสตริงเข้าด้วยกัน เรารู้จักมันในฐานะตัวดำเนินการบวกสำหรับการบวกค่าตัวเลข หลังจากที่เรากำหนดแล้ว เมื่อวางไว้ระหว่างจำนวนเต็ม มันจะบวกกัน เมื่อวางไว้ระหว่างสตริง มันจะเชื่อมต่อสตริงเหล่านั้นเข้าด้วยกัน

2 ตัวอย่าง

#include<iostream> 
using namespace std;

class ComplexNum {
private:
	int real, over;
public:
	ComplexNum(int rl = 0, int ov = 0) {
		real = rl;   
		over = ov; 
	}

	ComplexNum operator + (ComplexNum const &obj) {
		ComplexNum result;
		result.real = real + obj.real;
		result.over = over + obj.over;
		return result;
	}
	void print() { 
		cout << real << " + i" << over << endl; 
	}
};
int main()
{
	ComplexNum c1(10, 2), c2(3, 7);
	ComplexNum c3 = c1+c2;
	c3.print();
}

Output:

C++ ตัวอย่างที่ 2 ของผลลัพธ์การโอเวอร์โหลดตัวดำเนินการ

นี่คือภาพหน้าจอของรหัส:

C++ ตัวอย่างโค้ดการโอเวอร์โหลดตัวดำเนินการ 2

C++ ผลลัพธ์จากการโอเวอร์โหลดตัวดำเนินการ ตัวอย่างที่ 2

Code คำอธิบาย:

  1. รวมไฟล์ส่วนหัว iostream ลงในโปรแกรมของเราเพื่อใช้ฟังก์ชันต่างๆ
  2. รวมเนมสเปซมาตรฐานไว้ในโปรแกรมของเราเพื่อใช้คลาสโดยไม่ต้องเรียกมัน
  3. สร้างคลาสชื่อ ComplexNum เครื่องหมาย { จะเป็นจุดเริ่มต้นของตัวคลาส
  4. ใช้ตัวแก้ไขการเข้าถึงส่วนตัวเพื่อทำเครื่องหมายตัวแปรว่าเป็นส่วนตัว ซึ่งหมายความว่าสามารถเข้าถึงได้จากภายในชั้นเรียนเท่านั้น
  5. กำหนดตัวแปรจำนวนเต็มสองตัว จริงและมากกว่า
  6. ใช้ตัวแก้ไขการเข้าถึงแบบสาธารณะ (public access modifier) ​​เพื่อกำหนดให้คอนสตรัคเตอร์เป็นแบบสาธารณะ ซึ่งหมายความว่าจะสามารถเข้าถึงได้แม้จากภายนอกคลาส
  7. สร้างตัวสร้างคลาสและการเริ่มต้นตัวแปร
  8. เริ่มต้นค่าของตัวแปรจริง
  9. เริ่มต้นค่าของตัวแปรทับ
  10. จุดสิ้นสุดของตัวสร้าง
  11. เราจำเป็นต้องแทนที่ความหมายของตัวดำเนินการ +
  12. สร้างผลลัพธ์ชนิดข้อมูลประเภท ComplexNum
  13. ใช้ตัวดำเนินการ + กับตัวเลขเชิงซ้อน บรรทัดนี้จะเพิ่มส่วนจริงของตัวเลขเข้ากับส่วนจริงของตัวเลขอื่น
  14. ใช้ตัวดำเนินการ + กับตัวเลขเชิงซ้อน บรรทัดนี้จะเพิ่มส่วนจินตภาพของตัวเลขเข้ากับส่วนจินตภาพของตัวเลขอื่น
  15. โปรแกรมจะคืนค่าของผลลัพธ์ของตัวแปรเมื่อดำเนินการสำเร็จ
  16. สิ้นสุดนิยามความหมายใหม่ของตัวดำเนินการ + นั่นคือการโอเวอร์โหลด
  17. เรียกเมธอด print()
  18. พิมพ์ตัวเลขเชิงซ้อนใหม่หลังจากการบวกบนคอนโซล
  19. ส่วนท้ายของฟังก์ชัน print()
  20. จุดสิ้นสุดของเนื้อหาคลาส ComplexNum
  21. เรียกใช้ฟังก์ชัน main()
  22. ส่งค่าทั้งส่วนจริงและส่วนเชิงซ้อนที่ต้องการบวก โดยส่วนแรกของ c1 จะถูกบวกกับส่วนแรกของ c2 นั่นคือ 10+3 ส่วนที่สองของ c1 จะถูกบวกกับส่วนที่สองของ c นั่นคือ 2+7
  23. ดำเนินการโดยใช้ตัวดำเนินการโอเวอร์โหลด + และเก็บผลลัพธ์ไว้ในตัวแปร c3
  24. พิมพ์ค่าของตัวแปร c3 บนคอนโซล
  25. ส่วนท้ายของฟังก์ชัน main()

ในขณะที่โพลีมอร์ฟิซึมในขั้นตอนการคอมไพล์จะตัดสินใจตั้งแต่เนิ่นๆ โพลีมอร์ฟิซึมประเภทที่สองจะเลื่อนการเลือกไปจนถึงขั้นตอนการทำงาน

ความแตกต่างของรันไทม์

สิ่งนี้เกิดขึ้นเมื่อเมธอดของอ็อบเจ็กต์ถูกเรียกใช้/เรียกใช้ระหว่างรันไทม์ แทนที่จะเป็นในช่วงเวลาคอมไพล์ ความหลากหลายแบบรันไทม์ทำได้โดยการเอาชนะฟังก์ชัน ฟังก์ชันที่จะเรียกใช้/เรียกใช้จะถูกสร้างขึ้นในระหว่างรันไทม์

การเอาชนะฟังก์ชัน

การแทนที่ฟังก์ชันเกิดขึ้นเมื่อฟังก์ชันของคลาสพื้นฐานได้รับคำจำกัดความใหม่ในคลาสที่ได้รับ ในเวลานั้น เราสามารถพูดได้ว่าฟังก์ชันพื้นฐานถูกแทนที่แล้ว

ตัวอย่างเช่น:

#include <iostream>
using namespace std;
class Mammal {

public:
	void eat() {

		cout << "Mammals eat...";
	}

};

class Cow: public Mammal {

public:
	void eat() {

		cout << "Cows eat grass...";
	}
};
int main(void) {

	Cow c = Cow();

	c.eat();

	return 0;

}

Output:

C++ ฟังก์ชันที่เขียนทับเอาต์พุต

นี่คือภาพหน้าจอของรหัส:

C++ การเขียนทับฟังก์ชันโค้ด

Code คำอธิบาย:

  1. นำเข้าไฟล์ส่วนหัว iostream ลงในโปรแกรมของเราเพื่อใช้ฟังก์ชันต่างๆ
  2. รวมเนมสเปซมาตรฐานไว้ในโปรแกรมของเราเพื่อใช้คลาสโดยไม่ต้องเรียกมัน
  3. สร้างคลาสชื่อ Mammal { ถือเป็นจุดเริ่มต้นของเนื้อหาคลาส
  4. ใช้ตัวแก้ไขการเข้าถึงสาธารณะเพื่อตั้งค่าฟังก์ชันที่เรากำลังจะสร้างให้เข้าถึงได้แบบสาธารณะ จะสามารถเข้าถึงได้จากภายนอกชั้นเรียนนี้
  5. สร้างฟังก์ชั่นสาธารณะชื่อกิน { เป็นจุดเริ่มต้นของเนื้อหาฟังก์ชัน
  6. พิมพ์คำสั่งที่เพิ่มเข้าไปในฟังก์ชัน cout เมื่อเรียกใช้ฟังก์ชัน eat()
  7. ส่วนท้ายของฟังก์ชัน eat()
  8. ปิดท้ายด้วยคลาส Mammal
  9. สร้างคลาสชื่อ Cow ที่สืบทอดคลาส Mammal Cow เป็นคลาสที่ได้รับ ในขณะที่ Mammal เป็นคลาสพื้นฐาน { ถือเป็นจุดเริ่มต้นของคลาสนี้
  10. ใช้ตัวแก้ไขการเข้าถึงสาธารณะเพื่อทำเครื่องหมายฟังก์ชันที่เรากำลังจะสร้างว่าเข้าถึงได้แบบสาธารณะ จะสามารถเข้าถึงได้จากภายนอกชั้นเรียนนี้
  11. แทนที่ฟังก์ชัน eat() ที่กำหนดไว้ในคลาสพื้นฐาน { เป็นจุดเริ่มต้นของเนื้อหาฟังก์ชัน
  12. คำสั่งที่จะพิมพ์บนคอนโซลเมื่อมีการเรียกใช้ฟังก์ชันนี้
  13. ส่วนท้ายของฟังก์ชัน eat()
  14. จบร่างของคลาสวัว
  15. เรียกใช้ฟังก์ชัน main() { ถือเป็นจุดเริ่มต้นของเนื้อหาของฟังก์ชันนี้
  16. สร้างอินสแตนซ์ของคลาส Cow และตั้งชื่อให้ว่า c
  17. เรียกใช้ฟังก์ชัน eat() ที่กำหนดไว้ในคลาส Cow
  18. โปรแกรมจะต้องส่งคืนค่าเมื่อดำเนินการเสร็จสิ้น
  19. จุดสิ้นสุดของฟังก์ชัน main()

C++ ฟังก์ชั่นเสมือน

ฟังก์ชันเสมือนเป็นอีกวิธีหนึ่งในการนำโพลีมอร์ฟิซึมแบบรันไทม์มาใช้ใน C++เป็นฟังก์ชันพิเศษที่กำหนดในคลาสฐานและกำหนดใหม่ในคลาสที่สืบทอดมา หากต้องการประกาศฟังก์ชันเสมือน คุณควรใช้คีย์เวิร์ดเสมือน คีย์เวิร์ดควรอยู่ก่อนการประกาศฟังก์ชันในคลาสฐาน

หากคลาสฟังก์ชันเสมือนได้รับการสืบทอดมา คลาสเสมือนจะกำหนดฟังก์ชันเสมือนใหม่เพื่อให้เหมาะกับความต้องการ ตัวอย่างเช่น:

#include <iostream>  
using namespace std;
class ClassA {
		public:
		virtual void show() {
			cout << "The show() function in base class invoked..." << endl;
		}
	};
	class ClassB :public ClassA {
	public:
		void show() 	{
			cout << "The show() function in derived class invoked...";
		}
	};
	int main() {
		ClassA* a;   
		ClassB b;
		a = &b;
		a->show();      
	}

Output:

C++ เอาต์พุตฟังก์ชันเสมือน

นี่คือภาพหน้าจอของรหัส:

C++ รหัสฟังก์ชันเสมือน

Code คำอธิบาย:

  1. รวมไฟล์ส่วนหัว iostream ไว้ในโค้ดเพื่อใช้ฟังก์ชันต่างๆ
  2. รวมเนมสเปซมาตรฐานไว้ในโค้ดของเราเพื่อใช้คลาสโดยไม่ต้องเรียกมัน
  3. สร้างคลาสชื่อ ClassA
  4. ใช้ตัวแก้ไขการเข้าถึงสาธารณะเพื่อทำเครื่องหมายสมาชิกชั้นเรียนว่าเข้าถึงได้แบบสาธารณะ
  5. สร้างฟังก์ชันเสมือนชื่อ show() มันจะเป็นงานสาธารณะ
  6. ข้อความที่จะพิมพ์เมื่อเรียกใช้ show() endl คือ C++ คำสำคัญซึ่งหมายถึงบรรทัดสิ้นสุด มันเลื่อนเคอร์เซอร์ของเมาส์ไปที่บรรทัดถัดไป
  7. ส่วนท้ายของฟังก์ชันเสมือน show()
  8. ส่วนท้ายของคลาส ClassA
  9. การสร้างคลาสใหม่ชื่อ ClassB ที่สืบทอดคลาส ClassA ClassA กลายเป็นคลาสพื้นฐานในขณะที่ ClassB กลายเป็นคลาสที่ได้รับ
  10. ใช้ตัวแก้ไขการเข้าถึงสาธารณะเพื่อทำเครื่องหมายสมาชิกชั้นเรียนว่าเข้าถึงได้แบบสาธารณะ
  11. กำหนดฟังก์ชันเสมือน show() ที่ได้รับในคลาสพื้นฐานใหม่
  12. ข้อความที่จะพิมพ์บนคอนโซลเมื่อมีการเรียกใช้ฟังก์ชัน show() ที่กำหนดไว้ในคลาสที่ได้รับ
  13. ส่วนท้ายของฟังก์ชัน show()
  14. ส่วนท้ายของคลาสที่ได้รับ ClassB
  15. เรียกใช้ฟังก์ชัน main() ควรเพิ่มตรรกะของโปรแกรมภายในเนื้อหา
  16. สร้างตัวแปรพอยน์เตอร์ชื่อ a มันชี้ไปที่คลาสชื่อ ClassA
  17. สร้างอินสแตนซ์ของคลาสชื่อ ClassB อินสแตนซ์ได้รับชื่อ b
  18. กำหนดค่าที่จัดเก็บไว้ในที่อยู่ b ในตัวแปร a
  19. เรียกใช้ฟังก์ชัน show() ที่กำหนดไว้ในคลาสที่ได้รับ มีผลผูกพันล่าช้า
  20. ส่วนท้ายของฟังก์ชัน main()

เมื่อได้อธิบายกลไกทั้งสองแล้ว ตารางด้านล่างจะแสดงความแตกต่างระหว่างกลไกทั้งสองแบบ

ความแตกต่างระหว่างคอมไพล์กับเวลา ความแตกต่างระหว่างรันไทม์

นี่คือข้อแตกต่างที่สำคัญระหว่างทั้งสอง:

ความหลากหลายของเวลาคอมไพล์ ความหลากหลายแบบรันไทม์
เรียกอีกอย่างว่า การจับตัวในช่วงต้น หรือ โพลีมอร์ฟิซึมแบบคงที่ เรียกอีกอย่างว่า การจับตัวแบบล่าช้า/แบบไดนามิก หรือ โพลีมอร์ฟิซึมแบบไดนามิก
เมธอดนี้ถูกเรียก/เรียกใช้ระหว่างเวลาคอมไพล์ วิธีการนี้ถูกเรียก/เรียกใช้ในระหว่างรันไทม์
ใช้งานผ่านการโอเวอร์โหลดฟังก์ชันและการโอเวอร์โหลดตัวดำเนินการ ดำเนินการผ่านวิธีการแทนที่และฟังก์ชันเสมือน
ตัวอย่าง วิธีการโอเวอร์โหลด หลายวิธีอาจมีชื่อคล้ายกันแต่มีจำนวนหรือประเภทอาร์กิวเมนต์ต่างกัน ตัวอย่าง การเอาชนะวิธีการ หลายวิธีอาจมีชื่อคล้ายกันและมีต้นแบบเดียวกัน
การประมวลผลเร็วขึ้นเนื่องจากการค้นหาวิธีการเกิดขึ้นในระหว่างการคอมไพล์ การทำงานช้าลงเนื่องจากการค้นหาวิธีการเกิดขึ้นในระหว่างการทำงาน
Less มีความยืดหยุ่นในการแก้ไขปัญหาเนื่องจากทุกอย่างเป็นที่ทราบในระหว่างเวลาคอมไพล์ มีความยืดหยุ่นมากในการแก้ไขปัญหาที่ซับซ้อนเนื่องจากมีการค้นพบวิธีการระหว่างรันไทม์

คำถามที่พบบ่อย

การโอเวอร์โหลด (Overloading) คือการกำหนดฟังก์ชันหลายฟังก์ชันที่มีชื่อเดียวกันแต่มีพารามิเตอร์ต่างกัน โดยจะถูกกำหนดค่าในระหว่างการคอมไพล์โดยไม่ใช้การสืบทอด ส่วนการโอเวอร์ไรด์ (Overriding) คือการกำหนดฟังก์ชันของคลาสพื้นฐานที่สืบทอดมาใหม่ โดยใช้ลายเซ็นเดียวกันในคลาสที่สืบทอดมา โดยจะถูกกำหนดค่าในระหว่างการทำงานเมื่อฟังก์ชันนั้นถูกประกาศเป็น virtual

ฟังก์ชันเสมือนบริสุทธิ์ (pure virtual function) ถูกประกาศด้วยค่า `= 0` และไม่มีเนื้อหาในคลาสพื้นฐาน คลาสใดก็ตามที่มีฟังก์ชันนี้จะกลายเป็นคลาสเสมือนแบบสัมบูรณ์ (absolute function)tracคลาส t ซึ่งไม่สามารถสร้างอินสแตนซ์ได้โดยตรง และบังคับให้คลาสที่สืบทอดมาต้องจัดเตรียมการใช้งานของตนเอง

เมื่อคลาสประกาศฟังก์ชันเสมือน คอมไพเลอร์จะสร้างตารางเสมือน (vtable) ของตัวชี้ฟังก์ชัน แต่ละอ็อบเจ็กต์จะเก็บตัวชี้ที่ซ่อนอยู่ไปยัง vtable ของคลาส ดังนั้นตัวชี้ของคลาสพื้นฐานจะเรียกฟังก์ชันที่ถูกเขียนทับอย่างถูกต้องในขณะรันไทม์ผ่านการผูกมัดแบบล่าช้า (late binding)

ใช่แล้ว เทมเพลตช่วยให้ฟังก์ชันหรือคลาสหนึ่งๆ สามารถทำงานกับข้อมูลได้หลายประเภท โดยคอมไพเลอร์จะสร้างโค้ดเฉพาะประเภทในระหว่างการคอมไพล์ การเขียนโปรแกรมแบบเจเนริกนี้เป็นรูปแบบหนึ่งของโพลีมอร์ฟิซึมแบบสถิต ซึ่งเสริมกับการโอเวอร์โหลดฟังก์ชันและการโอเวอร์โหลดตัวดำเนินการ

เมื่อคุณลบอ็อบเจ็กต์ที่สืบทอดมาโดยใช้ตัวชี้จากคลาสพื้นฐาน เฉพาะดีสตรัคเตอร์เสมือนเท่านั้นที่จะรับประกันว่าดีสตรัคเตอร์ของอ็อบเจ็กต์ที่สืบทอดมาจะทำงานด้วย หากไม่มีดีสตรัคเตอร์เสมือน การทำความสะอาดจะไม่สมบูรณ์และทำให้เกิดการรั่วไหลของหน่วยความจำ การประกาศดีสตรัคเตอร์ของคลาสพื้นฐานให้เป็นเสมือนจะทำให้การทำลายทำงานแบบพหุรูป (polymorphic)

โพลีมอร์ฟิซึมช่วยให้อินเทอร์เฟซเดียวสามารถจัดการกับวัตถุได้หลายประเภท ลดโค้ดที่ซ้ำซ้อนและทำให้การบำรุงรักษาทำได้ง่ายขึ้น นอกจากนี้ยังสนับสนุนการออกแบบที่ยืดหยุ่นและขยายได้ โดยที่คลาสที่สืบทอดใหม่สามารถเสียบเข้าไปได้โดยไม่ต้องเปลี่ยนแปลงโค้ดที่มีอยู่ และยังช่วยให้สามารถสร้างรูปแบบที่มีประสิทธิภาพโดยใช้ตัวชี้และการอ้างอิงของคลาสพื้นฐานได้อีกด้วย

ใช่แล้ว ผู้ช่วยเขียนโค้ด AI จะแปลงความคิดเห็นสั้นๆ ให้กลายเป็นฟังก์ชันโอเวอร์โหลด คลาสพื้นฐานเสมือน และการเขียนทับที่สืบทอดมา พวกมันจัดการกับโค้ดซ้ำซากได้อย่างรวดเร็ว แต่คุณควรตรวจสอบคำหลักเสมือน ลายเซ็นฟังก์ชัน และความปลอดภัยของตัวทำลายก่อนที่จะคอมไพล์โค้ดที่สร้างขึ้น

ใช่. นักบิน GitHub ฟังก์ชันนี้จะแนะนำการประกาศฟังก์ชันเสมือน การเขียนทับคลาสที่สืบทอด และการโอเวอร์โหลดตัวดำเนินการขณะที่คุณพิมพ์ ช่วยลดความซ้ำซ้อนของโค้ดสำหรับลำดับชั้นการสืบทอด แต่คุณควรตรวจสอบคำหลัก virtual รูปแบบการลงนามที่ตรงกัน และพฤติกรรมการผูกมัดแบบล่าช้าที่ถูกต้องก่อนทำการสร้าง

สรุปโพสต์นี้ด้วย: