2007/Aug/29

ตืดต่อ เจ้าของ Blog ได้อีกที่หนึ่งที่นี่
http://DevGod.blogspot.com


นี่เป็นเอกสารที่เคยที่เคยมีโครงการจะนำไปตีพิมพ์ตั้งแต่ปี พ.ศ. 2547 แล้ว แต่เปลี่ยนใจ
คิดว่านำมาเผยแพร่บน Blog ให้นักศึกษาหรือบุคคลทั่วไปที่สนใจ save ไปอ่านน่าจะดีกว่า
เพราะงั้นข้อความหลายๆ จุดในเอกสารนี้จะใช้ำคำว่าหนังสือ ไม่ได้ใช้คำว่า Blog (ขณะที่ทำการเขียนหนังสือเล่มนี้ ผมยังไม่รู้จักคำว่า Blog เลยด้วยซ้ำ)


คลิก Link ตามนี้ได้เลยครับ



ปล. ในเอกสารทั้ง 14 บทนี้จะมี การใช้รูปประกอบจำนวน 16 รูป ซึ่งขณะนี้ยังไม่ได้ใส่เข้าไป ถ้าหากมันไม่มีรูปโชว์ในส่วนที่ควรจะมีก็ไม่ต้องแปลกใจนะ

เผยแพร่ครั้งแรก 08/29/2550

edit @ 2007/08/29 17:31:56
edit @ 2007/08/29 17:34:49

2007/Aug/29

Linked List

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

 

Student St[1000];

 

ถ้าหากคนที่ 200 ลาออกเราจำเป็นที่จะต้องลบข้อมูลคนที่ 200 และยังต้องทำการเลื่อนข้อมูลคนที่ 201 ให้มาเป็น 200 และทำการเลื่อนข้อมูลคนที่ 202 ให้มาเป็น 201 จนถึงคนที่ 1000 ให้มาเป็นคนที่ 999 ซึ่งการทำงานตามขั้นตอนที่ว่านี่จะค่อนข้างยุ่งยากและเสียเวลามาก

 Linkled list เป็นอัลกอริทึ่มทางวิทยาศาสตร์ที่จะสามารถแก้ไขปัญหานี้ได้ โดยหลักการทำงานของ Linkled list คือจะให้ Object แต่ละตัวสามารถเชื่อมต่อกันได้โดยที่ Object แต่ละตัวจะมีตัวชี้ของ Object ที่อยู่ข้างหน้า และถ้าเราต้องการที่จะเพิ่ม Object ขึ้นมาถ้า Object นั้นอยู่ตำแหน่งสุดท้ายก็ให้เรานำ Object ตัวสุดท้ายชี้ไปที่ Object นั้นได้เลย

 รูปแบบของ Linked listดูได้จากรูปที่ 14-1

 

 รูปที่ 14-1

 นอกจากนี้แล้ว Linked list ยังมีความสามารถอีกหลายอย่าง ในที่นี้จะยังไม่กล่าวถึงการ Insert Object หรือ การ Delete Object แต่จะกล่าวถึงการใช้ Linked list ในการชี้ไปที่ Object อื่นก่อน

 การทำให้ Object สามารถชี้ไปอีก Object หนึ่งโดยใช้ Data Member

 ถ้าเราสร้าง class แบบนี้

 class Student

{

 private:

 int Age;

 public:

 int GetAge(){return Age;}

   void SetAge(int Num1){ Age = Num1;}

  Student *StNext;

 

};

 เมื่อเราสร้าง Object  ที่มาจาก class Student ขึ้น เราก็สามารถกำหนดให้ Object ของ เราสามารถชี้ไปที่อีก Object หนึ่งได้ เนื่องจากเรามี Pointer  *StNext ที่สามารถชี้ไปที่ Object ที่สามารถสร้างมาจาก class Student ได้

โปรแกรมที่ 14-1 ตัวอย่างการการทำให้ Object สามารถชี้ไปอีก Object หนึ่งโดยใช้ Data Member

Source code

1:#include"iostream.h"

2:class Student

3:{

4: private:

5: int Age;

6: public:

7: int GetAge(){return Age;}

8: void SetAge(int Num1){ Age = Num1;}

9: Student *StNext;

10:

11:};

12:void ShowData(Student *SS)

13:{

14: cout << "Age of Student is " << SS->GetAge() << endl;

15: if (SS->StNext)ShowData(SS->StNext);

16:}

17:int main()

18:{

19: Student Miki;

20: Student Keakai;

21: Student Bank;

22:

23: Miki.StNext = &Keakai;

24: Keakai.StNext = &Bank;

25: Bank.StNext = 0;

26:

27: Miki.SetAge(30);

28: Keakai.SetAge(20);

29: Bank.SetAge(256);

30:

31: ShowData(&Miki);

32:

33: return 0;

34:}

Output

Age of Student is 30

Age of Student is 20

Age of Student is 256

อธิบาย Source code

 โปรแกรมนี้ได้มีการใช้ class Student ซึ่งได้อธิบายมาก่อนหน้านี้แล้ว

บรรทัดที่ 19 ถึง บรรทัดที่ 21:เป็นการสร้าง Object Miki,Keakai,Bank ที่เป็น class Student

บรรทัดที่ 22 ถึง บรรทัดที่ 25:เป็นการใช้ Data Meber St ของ แต่ละ Object ให้ชี้ไปที่ Object อีกตัวหนึ่งจนถึง Object สุดท้ายให้ชี้ไปที่ Null แทน

บรรทัดที่ 31:เป็นการใช้ Function ShowData() ซึ่ง Function นี้จะมีการทำงานคือ

เป็น Function ที่จะทำการรับที่อยู่ของ Object ประเภท Student มา จากนั้นจึงทำการแสดงอายุของ Object นั้น เสร็จแล้วก็จะทำการเช็คว่า Data Member StNext ของ Object นั้นเท่ากับ 0 หรือไม่ ถ้าเท่ากับ 0 ก็จะไม่ทำอะไรต่อ แต่ถ้าไม่เท่ากับ 0 ก็หมายความว่า StNext ได้ทำการชี้ไปที่ address ของ Object อื่น ก็ให้ใช้ Function ShowData อีกรอบ โดยส่งอาร์กิวเมนท์ไปคือ Object ที่โดน Object นี้ชี้อยู่

ในที่นี้หลักการทำงานของ โปรแกรมคือ

1.ตอนแรกส่งที่อยู่ของ Miki ไป หลังจากที่โปรแกรมทำการแสดงผลอายุแล้วก็ทำการเช็คว่า Miki ได้ชี้ไปที่ Object อื่นหรือไม่จาก StNext ซึ่งปรากฎว่าจริง ก็ให้ ทำ ShowData() โดยคราวนี้อาร์กิวเมนท์ที่ส่งไปคือ ที่อยู่ของ Keakai เพราะว่า Miki ชี้ที่ Keakai อยู่

2.ทำการแสดงผลอายุของ Keakai จากนั้นทำการเช็คว่า Keakai ได้ชี้ไปที่ Object อื่นหรือไม่ ซึ่งปรากฎว่าจริงก็ให้ทำ ShowData โดยคราวนี้อาร์กิวเมนท์ที่ส่งไปคือ ที่อยู่ของ Bank เพราะว่า Keakai ชี้ที่ Bank อยู่

3. ทำการแสดงผลอายุของ Bank เนื่องจาก Object Bank ไม่ได้ชี้ไปที่ที่อยู่ของ Object ใดเลยจึงไม่ต9ต้องทำงานต่อ

การใช้ Member Function ในการจัดการกับ Object ที่ชี้อยู่

ในโปรแกรมที่ 14-1 เราได้ใช้ Function ShowData ซึ่งเป็น Function จากภายนอก class คราวนี้เราจะใช้ Function ShowData ให้เป็น Member Function ที่อยู่ใน class Student

โปรแกรมที่ 14-2 การใช้ Member Function ในการจัดการกับ Object ที่ชี้อยู่

Source code

1:#include"iostream.h"

2:class Student

3:{

4: private:

5: int Age;

6: public:

7: int GetAge(){return Age;}

8: void SetAge(int Num1)

9: {

10: Age = Num1;

11: }

12:

13: Student *StNext;

14: void ShowData()

15: {

16: cout << "Age of Student is " << this->GetAge() << endl;

17: if (this->StNext) this->StNext->ShowData();

18: }

19:};

20:

21:

22:

23:int main()

24:{

25: Student Miki;

26: Student Keakai;

27: Student Bank;

28:

29: Miki.StNext = &Keakai;

30: Keakai.StNext = &Bank;

31: Bank.StNext = 0;

32:

33: Miki.SetAge(30);

34: Keakai.SetAge(20);

35: Bank.SetAge(256);

36:

37: Miki.ShowData();

38:

39: return 0;

40:}

Output จะเหมือนกับโปรแกรมที่ 14-1

 อธิบาย Source code

บรรทัดที่ 14 ถึง บรรทัดที่ 18:เป็นFunction ShowData ซึ่งจะเห็นได้ว่า Function นี้จะไม่ต้องมีการส่งอาร์กิวเมนท์ไป แต่การทำงานของ Function นี้จะขึ้นอยู่กับ ว่า Object ตัวไหนเรียกใช้ และถ้า Object นั้นมีการชี้ไปที่ Object อื่น โปรแกรมก็จะมีการทำงาน ShowData ของ Object ที่โดยชี้อยู่

 การใช้ Linked list ในการ Insert ข้อมูล

ในการที่เราจะใช้ โครงสร้าง Linked list เราจะต้องมี Pointer ที่ทำหน้าที่ชี้ Object ตัวแรกด้วย โดยปกติเราจะนิยมเรียกว่า Head หรือ First

เราสามารถใช้ Link list ในการ Insert ข้อมูลได้ ซึ่งจะทำให้ปัญหาในการใช้ array หมดไป โดยอัลกอริทึ่มในการ Insert ข้อมูลมีดังนี้

การ Insert ข้อมูลที่ตำแหน่งสุดท้าย

 1.ให้ Object ตัวสุดท้ายชี้ไปยัง Object ที่ Insert เข้ามา

2.ให้ Object ตัวที่ Insert เข้ามาชี้ไปยัง Null

ดูได้จากรูปที่ 14-2

 รูปที่ 14-2 แสดงรูปแบบการ Insert ข้อมูลเข้าไปที่ตำแหน่งสุดท้าย

การ Insert ข้อมูลเข้าไปที่ตำแหน่งแรกสุด

 1.ให้ Object ที่ Insert เข้ามาชี้ไปที่ Head ชี้อยู่

 2.ให้ Head ชี้ไปที่ Object ที่ Insert เข้ามา

ดูได้จากรูปที่ 14-3

 รูปที่ 14-3 แสดงรูปแบบการ Insert ข้อมูลเข้าไปที่ตำแหน่งแรกสุด

 

การ Insert ข้อมูลที่ตำแหน่งตรงกลาง

1.ให้ Object ที่ Insert เข้ามาชี้ไปที่ Object ที่ตำแหน่งที่ต้องการ

2.ให้ Object ที่อยู่ก่อนหน้าตำแหน่งที่ต้องการ ชี้ไปที่ Object ที่ Insert เข้ามา

 ดูได้จากรูปที่ 14-4

 รูปที่ 14-4 แสดงรูปแบบการ Insert ข้อมูลเข้าไปที่ตำแหน่งตรงกลาง

 

โปรแกรมที่ 14-3 ตัวอย่างการ Insert ข้อมูลเข้าไปที่ตำแหน่งสุดท้ายใน Linked list

Source code

1:#include"iostream.h"

2:#include"conio.h"

3:class Student

4:{

5: private:

6: int Age;

7: char Name[30];

8: public:

9: int GetAge(){return Age;}

10: void SetAge(int Num1){ Age = Num1;}

11: Student *StNext;

12:

13:};

14:Student Head;

15:void ShowData()

16:{

17: Student *Poi;

18: Poi = &Head;

19: Poi = Poi->StNext;

20: while(1==1)

21: {

22: cout << "Age of Student is " << Poi->GetAge() << endl;

23:

24: if (Poi->StNext==0)break;

25: Poi = Poi->StNext;

26: }

27:}

28:

29:void InsertData(Student *SInsert)

30:{

31:

32: Student *Poi;

33: Poi = &Head;

34: while(Poi->StNext !=0)

35: {

36: Poi =Poi->StNext;

37:

38: }

39:

40:

41: Poi->StNext = SInsert;

42: SInsert->StNext =0;

43:}

44:

45:int main()

46:{

47:

48: int choice;

49: int Age;

50:

51: Student Miki;

52: Student Keakai;

53: Student Bank;

54:

55: Head.StNext = &Miki;

56: Miki.StNext = &Keakai;

57: Keakai.StNext = &Bank;

58: Bank.StNext = 0;

59:

60: Miki.SetAge(30);

61: Keakai.SetAge(20);

62: Bank.SetAge(256);

63:

64: ShowData();

65: choice = 1;

66:

67: while(1==1)

68: {

69: Student *SIn = new Student;

70: cout << endl;

71: cout << " Menu." << endl;

72: cout << "1.Insert Data " << endl;

73: cout << "2.Exit " << endl;

74: cout << "Please choose menu:";

75: cin >> choice;

76: if (choice != 1)break;

77: cout << "Please enter Age :" ;

78: cin >> Age;

79: SIn->SetAge(Age);

80:

81: InsertData(SIn);

82:

83: clrscr();

84: ShowData();

85: }

86:

87:

88:

89: return 0;

90:}

Output

Age of Student is:30

Age of Student is:20

Age of Student is:256

 Menu.

1.Insert Data

2.Exit

Please choose menu:1

Please enter Age :66

เมื่อถึงตรงนี้โปรแกรมจะทำการ Clear หน้าจอ และ แสดงผล

Age of Student is:30

Age of Student is:20

Age of Student is:256

Age of Student is:66

 Menu.

1.Insert Data

2.Exit

Please choose menu:2

อธิบาย Source code

บรรทัดที่ 14:เป็นการประกาศให้ Head อยู่ในส่วนของ Global เพื่อที่จะให้ใช้ได้ทั้งโปรแกรม

บรรทัดที่ 55 ถึง บรรทัดที่ 58:เป็นการให้ Head ชี้ไปที่ Miki และก็เป็นการกำหนดให้ Object แต่ละตัวชี้ไปที่ตัวต่อไปจนถึง Object Bank ให้ชี้ไปที่ Null แทน เพราะเป็นตัวสุดท้าย

 การทำงานของ Function ShowData ในโปรแกรมนี้

 

 Function ShowData อยู่ระหว่างบรรทัดที่ 15 ถึง บรรทัดที่ 27 โดยจะมีการทำงานคือสร้าง Pointer ชื่อ Poi และให้ทำการชี้ไปที่ Head จากนั้นเป็นการกำหนดให้ Poi ชี้ไปที่ Poi->StNext คือชี้ไปที่ Object ที่ Head ชี้อยู่ แล้วก็ให้ทำการวน loop แสดงผล โดยมีเงื่อนไขในการออกจาก loop อยู่ในบรรทัดที่ 24: คือ 

if (Poi->StNext==0)break; จะเป็นการเช็คว่าถ้าหาก Object ได้มีการชี้ไปที่ Null จริง ก็จะถือว่าเป็นตัวสุดท้ายแล้วก็ให้ทำการออกจาก loop แต่ถ้าไม่จริงก็ให้ทำบรรทัดที่ 25 คือให้ Poi ทำการชี้ที่ Object Poi ทำการชี้อยู่ ส่วนสาเหตุที่ในการวน loop while ในบรรทัดที่ 20 ถึงมีเงื่อนไขให้ 1==1 จึงจะทำก็เพราะว่า เป็นเงื่อนไขที่ยังไงก็เป็นจริงอยู่แล้ว ในโปรแกรมนี้จะปล่อยให้ while ทำงานไปเรื่อยๆ ส่วน Source code ที่จะทำการออกจาก loop จะอยู่ในบรรทัดที่ 24 แทน

 ในที่นี้ถ้าหากเราใช้ Function ShowData เมื่อตอนรันโปรแกรมโดย

 Head  ชี้ไปที่  Miki

 Miki ชี้ไปที่ Keakai

 Keakai  ชี้ไปที่ Bank

 Bank ชี้ไปที่ Null

 เมื่อเราใช้ Function ShowData ก่อนที่จะถึง loop while  ตัว Poi ก็จะทำการชี้ไปที่ Miki เนื่องจาก Source code ในบรรทัดที่ 19

 รอบแรก ทำการแสดงผลอายุของ Miki จากนั้นก็เช็คเงื่อนไขว่าชี้ไปที่ Null หรือเปล่า ซึ่งปรากฎว่าไม่จริงก็จะให้ Poi ชี้ไปที่ Poi->StNext นั่นคือ Keakai

 รอบที่ 2 ทำการแสดงผลอายุของ Keakai จากนั้นก็เช็คเงื่อนไขว่าชี้ไปที่ Null หรือเปล่า ซึ่งปรากฎว่าไม่จริงก็จะให้ Poi ชี้ไปที่ Poi->StNext นั่นคือ Bank

 รอบที่ 3 ทำการแสดงผลอายุของ Bank จากนั้นก็เช็คเงื่อนไขว่าชี้ไปที่ Null หรือเปล่า ซึ่งปรากฎว่าจริงก็ให้ออกจาก loop

 Function InsertData ทำงานอย่างไร

 Function InsertData อยู่ในบรรทัดที่ 29 ถึง บรรทัดที่ 43 โดย Function นี้จะมีการับพารามิเตอร์เป็น Pointer ที่สามารถชี้ไปที่ Object ที่สร้างจาก class Student ได้ โดยจะมีการทำงานดังนี้

 บรรทัดที่ 32 และ บรรทัดที่ 33:สร้าง Poi เพื่อที่จะใช้หา Object ตัวสุดท้าย

 บรรทัดที่ 34 ถึง บรรทัดที่ 38:เป็นการวน loop ให้ Poi ชี้ไปที่ Poi->StNext ไปเรื่อยจนกว่า Poi-> จะเท่ากับ 0 ก็จะออกจาก loop(เงื่อนไขของเราคือถ้าไม่เท่ากับ 0 ก็จะทำการวนloop)

 บรรทัดที่ 41 ถึง บรรทัดที่ 42:กว่าจะทำงานถึงบรรทัดนี้ ถึงตอนนี้ Poi จะชี้ไปที่ Object สุดท้ายแล้วการทำงานของ 2 บรรทัดนี้คือ

1.ให้ Object สุดท้ายทำการชี้ไปที่ Object ที่ Insert เข้ามา

2.ให้ Object ตัวที่ Insert เข้ามาทำการชี้ไปที่ Null

โปรแกรมที่ 14-4 ตัวอย่างการ Insert ข้อมูลโดยมีการระบุตำแหน่ง

Source code

1:#include"iostream.h"

2:#include"conio.h"

3:class Student

4:{

5: private:

6: int Age;

7: char Name[30];

8: public:

9: int GetAge(){return Age;}

10: void SetAge(int Num1){ Age = Num1;}

11: Student *StNext;

12:

13:};

14:Student Head;

15:void ShowData()

16:{

17: Student *Poi;

18: Poi = &Head;

19: while(1==1)

20: {

21: Poi = Poi->StNext;

22: cout << "Age of Student is " << Poi->GetAge() << endl;

23:

24: if (Poi->StNext==0)break;

25:

26: }

27:}

28:

29:void InsertData(Student *SInsert,int Position)

30:{

31:

32: Student *Poi;

33: Poi = &Head;

34: int i=0;

35: while(1==1)

36: {

37: i++;

38: if(i== Position)break;

39: Poi = Poi->StNext;

40: }

41:

42: SInsert->StNext = Poi->StNext;

43: Poi->StNext = SInsert;

44:

45:}

46:

47:int main()

48:{

49:

50: int choice;

51: int Age;

52: int Position;

53:

54: Student Miki;

55: Student Keakai;

56: Student Bank;

57:

58: Head.StNext = &Miki;

59: Miki.StNext = &Keakai;

60: Keakai.StNext = &Bank;

61: Bank.StNext = 0;

62:

63: Miki.SetAge(30);

64: Keakai.SetAge(20);

65: Bank.SetAge(256);

66:

67: ShowData();

68:

69: while(1==1)

70: {

71: Student *SIn = new Student;

72: cout << endl;

73: cout << " Menu." << endl;

74: cout << "1.Insert Data " << endl;

75: cout << "2.Exit " << endl;

76: cout << "Please choose menu:";

77: cin >> choice;

78:

79: if (choice != 1)break;

80:

81: cout << "Please enter Age :" ;

82: cin >> Age;

83: cout << "Please enter Position :" ;

84: cin >> Position;

85:

86: SIn->SetAge(Age);

87:

88: InsertData(SIn,Position);

89:

90: clrscr();

91: ShowData();

92: }

93:

94:

95:

96: return 0;

97:}

Output

Age of Student is:30

Age of Student is:20

Age of Student is:256

 Menu.

1.Insert Data

2.Exit

Please choose menu:1

Please enter Age :66

Please enter Position:2

เมื่อถึงตรงนี้โปรแกรมจะทำการ Clear หน้าจอ และ แสดงผล

Age of Student is:30

Age of Student is:66

Age of Student is:20

Age of Student is:256

เพื่อให้เป็นการประหยัดเนื้อที่จะทำการแสดงผลเพียงเท่านี้

อธิบาย Source code

 โปรแกรมนี้จะคล้ายกับโปรแกรมที่ 14-3 แต่จะแตกต่างกันที่ Function InsertData จะต้องมีการรับอาร์กิวเมนท์ที่จะกำหนดตำแหน่งที่เราต้องการแทรกข้อมูลด้วย

 Function InsertData อยู่ระหว่างบรรทัดที่ 29 ถึง บรรทัดที่ 45: โดย Source code ของการหาตำแหน่งที่ต้องการอยู่ในบรรทัดที่ 35 ถึง บรรทัดที่ 40 มีหลักการทำงานคือ ให้ ตัว Poi ชี้ไปที่ Poi->StNext ไปเรื่อยๆในแต่ละรอบ และในแต่ละรอบก็ให้ตัวแปร i เพื่มอีก 1 และถ้าตัวแปร i เท่ากับ Position จริงก็ให้ออกจาก loop โดยที่ในการเช็คว่า i เท่ากับ Position หรือเปล่าจะทำก่อนที่จะให้ Poi ชี้ไปที่ Poi->SetNext เมื่อออกจาก loop Poi ก็จะชี้ไปที่ Object ที่มีตำแหน่งเท่ากับ Position –1

 เช่นถ้าเราส่งอาร์กิวเมนท์ Position เท่ากับ 1

 เมื่อมาถึงโปรแกรมก็จะทำการเพิ่มค่าให้กับ i อีก1 จากนั้นจึงทำการเช็คเงื่อนไขว่าเท่ากับ Position จริงหรือเปล่า ซึ่งปรากฎว่าจริงก็ให้ออกจาก loop ไปก่อนโดยที่ Poi ยังไม่ได้ชี้ไปที่ Poi->StNext เลยเท่ากับว่าตอนนี้ Poi ชี้ไปที่ Head ไม่ได้ชี้ไปที่ Object ที่ 1

 จากนั้นจึงทำการกำหนดให้

Sinsert->StNext = Poi.StNext;

ถ้าหาก Poi ชี้ไป Head จริงก็จะมี StNext ชี้ไปที่ Miki จริงก็จะเป็นการกำหนดให้ Object ที่ Insert เข้ามามี StNext ชี้ไปที่ Miki

Poi->StNext = SInsert;

ถ้าหาก Poi ชี้ไปที่ Head จริงก็จะเป็นการกำหนดให้ Head มี StNext ชี้ไปที่ Object ที่ Insert เข้ามา

การ Insert Object โดยใช้การกำหนดชื่อ

ในกรณีที่ Object แต่ละตัวของเรามีชื่อเป็นสมาชิกของ Object เราอาจจะใช้ Linked list ในการInsert

Object โดยที่เราจะกำหนดชื่อคนที่เราต้องการไปแทนที่ในตำแหน่งนั้นแทนก็ได้ เช่นข้อมูลมีลักษณะดังนี้

 Miki Keakai Bank

 แล้วเราต้องการเพิ่ม Object Oak โดยที่เรากำหนดให้ต้องไปแทนที่ บริเวณที่ Miki อยู่ ก็จะเป็นแบบนี้

Oak Miki Keakai Bank

โปรแกรมที่ 14-5 ตัวอย่างการการ Insert Object โดยใช้การกำหนดชื่อ

Source code

1:#include"iostream.h"

2:#include"conio.h"

3:#include"string.h"

4:class Student

5:{

6: private:

7: int Age;

8: char Name[30];

9: public:

10: int GetAge(){return Age;}

11: void SetAge(int Num1){ Age = Num1;}

12: char *GetName(){return Name;}

13: void SetName(char Na[]){ strcpy(Name,Na);}

14: Student *StNext;

15:

16:};

17:Student Head;

18:void ShowData()

19:{

20: Student *Poi;

21: Poi = &Head;

22: while(1==1)

23: {

24: Poi = Poi->StNext;

25: cout << "Name of Student is " << Poi->GetName() << endl;

26:

27: if (Poi->StNext==0)break;

28:

29: }

30:}

31:

32:void InsertData(Student *SInsert,char Name[])

33:{

34:

35: Student *Poi;

36: Poi = &Head;

37:

38: while(1==1)

39: {

40:  Poi = Poi->StNext;

41: if(strcmp(Poi->GetName(),Name)==0)break;

42:

43: }

44:

45: SInsert->StNext = Poi->StNext;

46: Poi->StNext = SInsert;

47:}

48:

49:

50:

51:int main()

52:{

53:

54: int choice;

55: int Age;

56: 

57: char Name[30];

58: char Namebefore[30];

59:

60: Student Miki;

61: Student Keakai;

62: Student Bank;

63:

64: Head.StNext = &Miki;

65: Miki.StNext = &Keakai;

66: Keakai.StNext = &Bank;

67: Bank.StNext = 0;

68:

69: Miki.SetName("Miki");

70: Keakai.SetName("Keakai");

71: Bank.SetName("Bank");

72:

73:

74: ShowData();

75:

76: while(1==1)

77: {

78: Student *SIn = new Student;

79: cout << endl;

80: cout << " Menu." << endl;

81: cout << "1.Insert Data " << endl;

82: cout << "2.Exit " << endl;

83: cout << "Please choose menu:";

84: cin >> choice;

85:

86: if (choice != 1)break;

87:

88: cout << "Please enter Name:" ;

89: cin >> Name;

90: cout << "Please enter Name before:" ;

91: cin >> Namebefore;

92:

93: SIn->SetName(Name);

94:

95: InsertData(SIn,Namebefore);

96:

97: clrscr();

98: ShowData();

99: }

100:

101:

102:

103: return 0;

104:}

Output

Name of Student is Miki

Name of Student is Keakai

Name of Student is Bank

 Menu.

1.Insert Data

2.Exit

Please choose menu:1

Please enter Name:Oak

Please enter Name before:Miki

เมื่อมาถึงตรงนี้โปรแกรมจะทำการ เคลียร์หน้าจอและแสดง

Name of Student is Miki

Name of Student is Oak

Name of Student is Keakai

Name of Student is Bank

 เพื่อความประหยัดเนื้อที่จึงขอแสดง Output เพียงเท่านี้

อธิบาย Source code

 โปรแกรมนี้ class Student จะมีการใช้ Member Function ในการกำหนดชื่อ และ การนำชื่อออกมาใช้ด้วยโดย Member Function นั้นคือ SetName และ GetName ใน Function InsertData จะต้องมีการส่งอาร์กิวเมนท์ชื่อของ Object ที่เราต้องการให้ไปแทนที่ด้วย

Function InsertDataจะอยู่ระหว่างบรรทัดที่ 32 ถึง บรรทัดที่ 47:

การทำงานของ Function InsertData คือ จะทำการ วน loop เพื่อที่จะให้ Poi ทำการชี้ไปที่ Poi->StNext ไปเรื่อย ส่วนเงื่อนไขที่จะทำให้ออกจาก loop อยู่ในบรรทัดที่ 41

if(strcmp(Poi->GetName(),Name)==0)break;

เป็นการใช้ Function strcmp เพื่อที่จะใช้ในการเปรียบเทียบ String 2 String ถ้าหาก 2 String นี้มีค่าเท่ากันค่าที่ได้จาก Function จะเท่ากับ 0 ซึ่งถ้าเป็นแบบนั้นจริงก็ให้ออกจาก loop

จากนั้นในบรรทัดที่ 45 และ บรรทัดที่ 46 เป็นการให้ Object ที่ Insert เข้าไปแทรกอยู่ต่อจาก Poi

การนับจำนวนของ Object ที่สร้างขึ้นมาใน List

ในการใช้ Linked list เราอาจจะมีความจำเป็นที่จะต้องการทราบจำนวนของ Object ที่มีอยู่ใน list ซึ่งเราอาจจะทำได้โดยเขียนFunction ขึ้นมาซึ่งจะทำการวน loop เพื่อให้ Pointer ชี้ไปที่ Object และเช็คว่า Object นั้นชี้ไปที่ Null หรือเปล่าถ้าไม่ใช่ก็ทำการนับ จนกว่าจะใช่ก็ได้ ซึ่งจะทำให้เราทราบจำนวนของ Object ที่อยู่ใน list

โปรแกรมที่ 14-6 ตัวอย่างการสร้าง Function เพื่อนับจำนวน Object

Source code

1:#include"iostream.h"

2:#include"conio.h"

3:#include"string.h"

4:class Student

5:{

6: private:

7: int Age;

8: char Name[30];

9: public:

10: int GetAge(){return Age;}

11: void SetAge(int Num1){ Age = Num1;}

12: char *GetName(){return Name;}

13: void SetName(char Na[]){ strcpy(Name,Na);}

14: Student *StNext;

15:

16:};

17:Student Head;

18:

19:int Count()

20:{

21: Student *Poi;

22: Poi= &Head;

23: int i=0;

24: while(1==1)

25: {

26: if(Poi->StNext==0)break;

27: i++;

28: Poi = Poi->StNext;

29: }

30: return i;

31:}

32:void ShowData()

33:{

34: Student *Poi;

35: Poi = &Head;

36: while(1==1)

37: {

38: Poi = Poi->StNext;

39: cout << "Name of Student is " << Poi->GetName() << endl;

40:

41: if (Poi->StNext==0)break;

42:

43: }

44: cout << " Number of Student is :" << Count();

45:}

46:

47:void InsertData(Student *SInsert,char Name[])

48:{

49:

50: Student *Poi;

51: Poi = &Head;

52: if(strcmp(Name,"") !=0)

53: {

54: while(1==1)

55: {

56:

57: if(strcmp(Poi->StNext->GetName(),Name)==0)break;

58:  Poi = Poi->StNext;

59: }

60:

61: SInsert->StNext = Poi->StNext;

62: Poi->StNext = SInsert;

63: }

64: else

65: {

66: Poi->StNext =SInsert;

67: SInsert->StNext =0;

68: }

69:

70:}

71:

72:

73:

74:

75:int main()

76:{

77:

78: int choice;

79:

80:

81: char Name[30];

82: char Namebefore[30];

83:

84: Student Miki;

85: Student Keakai;

86: Student Bank;

87:

88: Head.StNext = &Miki;

89: Miki.StNext = &Keakai;

90: Keakai.StNext = &Bank;

91: Bank.StNext = 0;

92:

93: Miki.SetName("Miki");

94: Keakai.SetName("Keakai");

95: Bank.SetName("Bank");

96:

97:

98: ShowData();

99:

100: while(1==1)

101: {

102: Student *SIn = new Student;

103: cout << endl;

104: cout << " Menu." << endl;

105: cout << "1.Insert Data " << endl;

106: cout << "2.Exit " << endl;

107: cout << "Please choose menu:";

108: cin >> choice;

109:

110: if (choice == 2)break;

111: else

112: {

113: cout << "Please enter Name:" ;

114: cin >> Name;

115: if (Count()>0)

116: {

117: cout << "Please enter Name before:" ;

118: cin >> Namebefore;

119: }

120: else

121: strcpy(Namebefore,"");

122:

123: SIn->SetName(Name);

124: InsertData(SIn,Namebefore);

125:  break;

126: }

127:

128: clrscr();

129: ShowData();

130: }

131:

132:

133:

134: return 0;

135:}

Output

 โปรแกรมนี้ใน Function ShowData จะทำการแสดงจำนวนของ Object ทั้งหมดที่อยู่ใน list ด้วย เพื่อเป็นการประหยัดเนื่อที่จึงไม่นำ Output มาแสดงให้เห็น

อธิบาย Source code

 Function Count มีไว้เพื่อใช้นับจำนวน Object ที่อยู่ใน list อยู่ระหว่างบรรทัดที่ 19 ถึง บรรทัดที่ 31

 มีการทำงานคือ

 ในบรรทัดที่ 24 ถึง บรรทัดที่ 29 จะทำการวน loop เพื่อนับจำนวน Object โดยใช้ตัวแปร i

 โดยที่ในแต่ละรอบเราจะให้ Poi ชี้ไปที่ Poi->StNext ไปเรื่อยๆจนกว่า Poi->StNext จะเท่ากับ Null ก็ให้ ออกจาก loop ถึงตอนนั้นตัวแปร i จะมีค่าเท่ากับ จำนวน Object

 การ Delete Object

 เราสามารถใช้ Linked list ในการที่ จะ Insert Object เราก็จะสามารถ Delete Object ได้ด้วยโดยอัลกอริทึ่มของการ Delete Object มีดังนี้

 การ Delete Object

 1.ให้ทำการหา Object ที่ต้องการ Delete ในที่นี้เรียกว่า Delete

 2.ให้ทำการหา Object ที่ชี้อยู่ที่ตำแหน่งที่ต้องการ Delete ในที่นี้เรียกว่า before

 3.กำหนด before ชี้ไปที่ ตำแหน่งที่ Delete ชี้อยู่

 4.Delete Object ที่ต้องการ (ไม่ได้แสดงในภาพ)

ดูได้จากรูปที่ 14-5

 รูปที่ 14-5 แสดงรูปแบบการ Delete ข้อมูล 

 เราไม่สามารถ Delete Object ที่ไม่ได้สร้างบน free store ได้ โปรแกรมนี้จึงจะมีการทำงาน ให้ สร้าง Object จากFunction Insert Object เท่านั้น

โปรแกรมที่ 14-6 ตัวอย่างการ Delete Object

Source code

1:#include"iostream.h"

2:#include"conio.h"

3:#include"string.h"

4:#include"iomanip.h"

5:class Student

6:{

7: private:

8: int Age;

9: int Score;

10: char Name[30];

11: public:

12: int GetAge(){return Age;}

13: void SetAge(int Num1){ Age = Num1;}

14: char *GetName(){return Name;}

15: void SetName(char Na[])

16: {

17: strcpy(Name,Na);

18: }

19: int GetScore(){return Score;}

20: void SetScore(int Num1){Score = Num1;}

21: Student *StNext;

22:

23:};

24:Student Head;

25:

26:int Count()

27:{

28: Student *Poi;

29: Poi= &Head;

30: int i=0;

31: while(1==1)

32: {

33: if(Poi->StNext==0)break;

34: i++;

35: Poi = Poi->StNext;

36: }

37: return i;

38:}

39:

40:void ShowData()

41:{

42: Student *Poi;

43: Poi = &Head;

44: cout << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl;

45: cout << " Name Age Score" << endl;

46: cout << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl;

47: if(Count() > 0)

48: {

49:

50: while(1==1)

51: {

52:  if (Poi->StNext==0)break;

53: Poi = Poi->StNext;

54:

55: cout << setw(20) << Poi->GetName();

56: cout << setw(10) << Poi->GetAge();

57: cout << setw(8) << Poi->GetScore();

58: cout << endl;

59: }

60: }

61: else

62: cout << " No data " << endl << endl;

63: cout << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl;

64: cout << " Number of Student is :" << Count();

65:}

66:

67:void InsertData(Student *SInsert,char Name[])

68:{

69:

70: Student *Poi;

71: Poi = &Head;

72: if(strcmp(Name,"") !=0)

73: {

74: while(1==1)

75: {

76:

77: if(strcmp(Poi->StNext->GetName(),Name)==0)break;

78:  Poi = Poi->StNext;

79: }

80:

81: SInsert->StNext = Poi->StNext;

82: Poi->StNext = SInsert;

83: }

84: else

85: {

86: Poi->StNext =SInsert;

87: SInsert->StNext =0;

88: }

89:

90:}

91:

92:void DeleteData(char Name[])

93:{

94:

95: Student *Poi;

96: Student *PoiBefore;

97: Poi = &Head;

98: PoiBefore = &Head;

99:

100: Poi = Poi->StNext;

101:

102: while(1==1)

103: {

104: if(strcmp(Poi->GetName(),Name)==0)break;

105: PoiBefore = Poi;

106: Poi = Poi->StNext;

107: }

108:

109: if(Count() > 1)

110: PoiBefore->StNext = Poi->StNext;

111: else

112: PoiBefore->StNext =0;

113:

114:

115: delete Poi;

116:}

117:

118:

119:int main()

120:{

121:

122: int choice;

123:

124: int Age;

125: int Score;

126:

127: char Name[30];

128: char Namebefore[30];

129:

130: Head.StNext =0;

131:

132: while(1==1)

133: {

134: Student *SIn = new Student;

135: cout << endl;

136: cout << "  Menu." << endl;

137: cout << " 1.Insert Data " << endl;

138: cout << " 2.Delete Data " << endl;

139: cout << " 3.Show Data " << endl;

140: cout << " 4.Exit " << endl;

141: cout << "Please choose menu:";

142: cin >> choice;

143:

144: if (choice == 4)break;

145: switch(choice)

146: {

147: case 1:

148: cout << " Insert Data" << endl;

149: cout << " Please enter Name:" ;

150: cin >> Name;

151: cout << " Please enter Age:";

152: cin >> Age;

153: cout << " Please enter Score:";

154: cin >> Score;

155:  if(Count() > 0)

156: {

157: cout << "Please enter Name before:" ;

158: cin >> Namebefore;

159: }

160: else

161: strcpy(Namebefore,"");

162:

163: SIn->SetName(Name);

164: SIn->SetAge(Age);

165: SIn->SetScore(Score);

166:

167: InsertData(SIn,Namebefore);

168:

169: clrscr();

170: break;

171:

172: case 2:

173: if(Count() > 0)

174: {

175: cout << " Delete Data" << endl;

176: cout << "Please enter Name:";

177: cin >> Name;

178: DeleteData(Name);

179: }

180: else

181: cout << "Not have data" << endl;

182:

183: clrscr();

184: break;

185: case 3:

186: clrscr();

187: ShowData();

188:

189: }

190:

191: }

192:

193:

194: return 0;

195:}

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

อธิบาย Source code

 โปรแกรมนี้ได้มีการใช้ Function DeleteData เพื่อที่จะเอาไว้ลบข้อมูลใน list โดยที่ถ้าเราจะใช้ Function นี้เราต้องส่งชื่อของคนที่เราต้องการลบไปด้วย

 Function นี้อยู่ระหว่างบรรทัดที่ 92 ถึง บรรทัดที่ 116โดยการทำงานของ Function คือ เราจะต้องสร้างตัว Poi เพื่อที่จะทำการหาตัวที่ต้องการลบและก็ให้ Poi ชี้ไปที่ตัวนั้น และเรายังต้องสร้าง Poibefore อีกตัวหนึ่งด้วยเพื่อที่จะทำการชี้ไปที่ Object ที่ StNext จะชี้ไปที่ Object ที่ต้องการลบ

 เช่นถ้าเราต้องการลบ Object แรก

 ตัว Poi จะชี้ไปที่ Object แรก

 ตัว Poibefore จะชี้ไปที่ Head เพราะว่า StNext ของ Head จะชี้ไปที่ Object แรก

 Source code ในส่วนของการหา Object ที่ต้องการลบจะอยู่ในบรรทัดที่ 102 ถึง บรรทัดที่ 107 โดยมีหลัการทำงานคือให้วน loop ไปเรื่อยๆ จนกว่า Poi->GetName() จะเท่ากับ Name ที่รับพารามิเตอร์มาโดยใช้ Function strcmp ในการเช็คจากนั้นจะมีการเช็คว่าจำนวนทั้งหมดของ Object มากกว่า 1 หรือเปล่า

 ถ้ามากกว่า

 ก็ให้ Poibefore->StNext = Poi->StNext;

 ถ้าหากเราต้องการลบ Object แรกก็จะเป็นการให้

  Head->StNext ไปชี้ที่ Object ที่ 2

 ถ้าไม่มากกว่า ก็หมายความว่ามี Object เดียว

 ก็ให้ Poibefore->StNext = 0;

 ถ้ามีแค่ Object เดียวก็ให้ Head ไปชี้ที่ Null แทน

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

 ความเป็นจริงแล้วเราไม่จำเป็นต้องเช็คจำนวนของ Object ก็ได้ว่าเหลือตัวสุดท้ายหรือเปล่า ในกรณีที่เรา ลบ Object สุดท้าย ซึ่ง StNext ของ Object สุดท้ายจะชี้ไปที่ Null อยู่แล้ว เพราะฉะนั้น

Poibefore->StNext = Poi->StNext

ก็จะเท่ากับ

Poibefore->StNext = 0

ในที่นี้เพื่อให้ Source code ดูง่ายก็เลยเขียนแบบนี้

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

การใช้ Class สร้าง Linked list

 เราสามารถสร้าง class เพื่อที่จะทำหน้าที่บรรจุ Object ให้มีการทำงานแบบ Linked list ได้ โดยปกติจะนิยมตั้งชื่อ class ประเภทนี้ว่า collection หรือไม่ก็ตั้งชื่อให้มีตัว s ต่อท้ายชื่อ class ที่จะถูกบรรจุ เช่น

 เรามี class Student แล้วเราต้องการสร้าง class ที่ทำหน้าที่บรรจุด Student เราอาจจะตั้งชื่อ Students ก็ได้

โปรแกรมที่ 14-8 ตัวอย่างการสร้าง class ที่ทำหน้าที่เป็น บรรจุด Object

Source code

1:#include"iostream.h"

2:#include"conio.h"

3:#include"string.h"

4:#include"iomanip.h"

5:class Student

6:{

7: private:

8: int Age;

9: int Score;

10: char Name[30];

11: public:

12: int GetAge(){return Age;}

13: void SetAge(int Num1){ Age = Num1;}

14: char *GetName(){return Name;}

15: void SetName(char Na[])

16: {

17: strcpy(Name,Na);

18: }

19: int GetScore(){return Score;}

20: void SetScore(int Num1){Score = Num1;}

21: Student *StNext;

22:

23:};

24:

25:

26:class Collection

27:{

28: public:

29: Student Head;

30: int Count();

31:  void ShowData();

32: void InsertData(Student *,char []);

33: void DeleteData(char []);

34:};

35:

36:int Collection::Count()

37:{

38: Student *Poi;

39: Poi= &Head;

40: int i=0;

41: while(1==1)

42: {

43: if(Poi->StNext==0)break;

44: i++;

45: Poi = Poi->StNext;

46: }

47: return i;

48:}

49:

50:void Collection::ShowData()

51:{

52: Student *Poi;

53: Poi = &Head;

54: cout << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl;

55: cout << " Name Age Score" << endl;

56: cout << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl;

57: if(Count() > 0)

58: {

59:

60: while(1==1)

61: {

62: if (Poi->StNext==0)break;

63: Poi = Poi->StNext;

64:

65: cout << setw(20) << Poi->GetName();

66: cout << setw(10) << Poi->GetAge();

67: cout << setw(8) << Poi->GetScore();

68: cout << endl;

69: }

70: }

71: else

72: cout << " No data " << endl << endl;

73: cout << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl;

74: cout << " Number of Student is :" << Count();

75:}

76:

77:void Collection::InsertData(Student *SInsert,char Name[])

78:{

79:

80: Student *Poi;

81: Poi = &Head;

82: if(strcmp(Name,"") !=0)

83: {

84: while(1==1)

85: {

86://

87: if(strcmp(Poi->StNext->GetName(),Name)==0)break;

88:  Poi = Poi->StNext;

89: }

90:

91: SInsert->StNext = Poi->StNext;

92: Poi->StNext = SInsert;

93: }

94: else

95: {

96: Poi->StNext =SInsert;

97: SInsert->StNext =0;

98: }

99:

100:}

101:

102:void Collection::DeleteData(char Name[])

103:{

104:

105: Student *Poi;

106: Student *PoiBefore;

107: Poi = &Head;

108: PoiBefore = &Head;

109:

110: Poi = Poi->StNext;

111:

112: while(1==1)

113: {

114: if(strcmp(Poi->GetName(),Name)==0)break;

115: PoiBefore = Poi;

116: Poi = Poi->StNext;

117: }

118:

119: if(Count() > 1)

120: PoiBefore->StNext = Poi->StNext;

121: else

122: PoiBefore->StNext =0;

123:

124:

125: delete Poi;

126:}

127:

128:

129:int main()

130:{

131:

132: int choice;

133:

134: int Age;

135: int Score;

136:

137: char Name[30];

138: char Namebefore[30];

139: Collection Cl;

140:

141: Cl.Head.StNext =0;

142:

143: while(1==1)

144: {

145: Student *SIn = new Student;

146: cout << endl;

147: cout << "  Menu." << endl;

148: cout << " 1.Insert Data " << endl;

149: cout << " 2.Delete Data " << endl;

150: cout << " 3.Show Data " << endl;

151: cout << " 4.Exit " << endl;

152: cout << "Please choose menu:";

153: cin >> choice;

154:

155: if (choice == 4)break;

156: switch(choice)

157: {

158: case 1:

159: cout << " Insert Data" << endl;

160: cout << " Please enter Name:" ;

161: cin >> Name;

162: cout << " Please enter Age:";

163: cin >> Age;

164: cout << " Please enter Score:";

165: cin >> Score;

166: if(Cl.Count() > 0)

167: {

168: cout << "Please enter Name before:" ;

169: cin >> Namebefore;

170: }

171: else

172: strcpy(Namebefore,"");

173:

174: SIn->SetName(Name);

175: SIn->SetAge(Age);

176: SIn->SetScore(Score);

177:

178: Cl.InsertData(SIn,Namebefore);

179:

180: clrscr();

181: break;

182:

183: case 2:

184: if(Cl.Count() > 0)

185: {

186: cout << " Delete Data" << endl;

187: cout << "Please enter Name:";

188: cin >> Name;

189: Cl.DeleteData(Name);

190: }

191: else

192: cout << "No data" << endl;

193:

194: clrscr();

195: break;

196: case 3:

197: clrscr();

198: Cl.ShowData();

199:

200: }

201:

202: }

203:

204: return 0;

205:}

Output โปรแกรมนี้สามารถทำงานได้เหมือนโปรแกรมที่ 14-7 จึงไม่นำ Output มาแสดงให้ดู และก็ยังไม่มีส่วน อธิบาย Source code ด้วยเพราะว่า Source code จะคล้ายกับโปรแกรมที่ 14-7 เพียงแต่ Function ต่างๆจะถูกบรรจุใน class Collection

Double Linked list

 Linked list ที่กล่าวมาก่อนหน้านี้เรียกได้ว่าเป็น Single Linked list นอกจาก Linked list แบบ Single แล้ว เรายังสามารถสร้าง Linked list อีกรูปแบบหนึ่งได้ โดยเราจะเรียกว่า Double Linked list โดยที่ Double Linked list จะมีการทำงานคล้าย Single Linked list มาก จะแตกต่างกันก็ตรงที่ Object แต่ละตัวนอกจากจะมี Pointer Nextที่สามารถชี้ไปที่ Object ตัวต่อไปแล้วยังมี Pointer อีกตัวหนึ่งที่จะทำการชี้ไปที่ Object ตัวก่อนหน้านี้ด้วย โดยปกติแล้วเรานิยมเรียก Pointer ที่ทำหน้าที่แบบนี้ว่า Back หรือ Previous

 

 

 

 

 

 

 

 

 

 

 

 

 

2007/Aug/29

Polymorphism

 คือการที่ Member Function ของคลาสมีพฤติกรรมต่างกัน ไม่ได้มีการทำงานแค่แบบเดียว ขึ้นอยู่กับว่า เราต้องการให้ Function นั้นมีพฤติกรรมอย่างไร Function ที่สามารถทำงานได้แบบนั้นเราจะเรียกว่า virtual Function ใน C++ ถ้าเราต้องการใช้ Polymorphism เราต้องมีการ Inheritance ก่อน

virtual Function

 คือ Function ที่มี ชื่อและ prototype ของ class แม่เหมือนกับ class ลูก โดยที่ class แม่จะต้องมีคำว่า virtual ไว้หน้าชื่อ Function ด้วย

 เช่น

class Programmer

{

 public:

 virtual void WriteProgram()

 {

 cout << "Write Program";

 }

};

 

class DatabaseProgrammer:public Programmer

{

 public:

 void WriteProgram()

 {

 cout << "Write Database Program";

 }

};

ในที่นี้เราได้สร้าง virtual Function ขึ้นมาชื่อ WriteProgram จะเห็นได้ว่า class แม่ จะต้องมีคำว่า virtual นำหน้าชื่อ Function ด้วย

รูปแบบของ การใช้ Polymorphism

 ถ้าเราจะใช้ Polymorphism ใน C++ เราต้องสร้าง Pointer ที่เป็นชนิดของ class แม่ก่อน เช่น

 Programmer *Poi;

 จากนั้นเราจึงสร้าง Object ของ class ลูก และให้ Pointer ชี้ไปที่ Object นั้น

 DatabaseProgrammer Db;

 Poi = &Db;

 ถึงตอนนี้ถ้าเราใช้ Member Function WriteProgram ก็จะเป็น Function ของ class DatabaseProgrammer

 ใน C++ Pointer ที่เป็นประเภทของ class แม่สามารถชี้ไปที่ Object ของ class แม่ หรือของ class ลูกก็ได้  แต่ Pointer ที่เป็นประเภทของ class ลูก จะไม่สามารถชี้ไปที่ Object ของ class แม่ได้ เช่น

 DatabaseProgrammer *PoiDb;

 Programmer Pg;

 PoiDb = &Pg; // แบบนี้จะถือว่าผิด

โปรแกรมที่ 13-1 ตัวอย่างการใช้ virtual Function

Output

1:#include"iostream.h"

2:class Programmer

3:{

4: public:

5: virtual void WriteProgram()

6: {

7: cout << "Write Program";

8: }

9:};

10:

11:class DatabaseProgrammer:public Programmer

12:{

13: public:

14: void WriteProgram()

15: {

16: cout << "Write Database Program";

17: }

18:};

19:

20:int main()

21:{

22: Programmer *Poi;

23: Programmer Pg;

24: DatabaseProgrammer Db;

25:

26: Poi = &Pg;

27: Poi->WriteProgram();

28:

29: cout << endl;

30:

31: Poi = &Db;

32: Poi->WriteProgram();

33:

34: return 0;

35:}

Output

Write Program

Write Database Program

อธิบาย Source code

 โปรแกรมนี้ได้มีการใช้ class Programmer และ class DatabaseProgramer ซึ่งได้อธิบายไว้ก่อนหน้านี้แล้ว

บรรทัดที่ 22:เป็นการสร้าง Pointer ที่เป็นประเภท class Programmer

บรรทัดที่ 23 และ บรรทัดที่ 24:ได้มีการสร้าง Object จาก class Programmer และ Object จาก class DatabaseProgrammer ซึ่ง Object ทั้ง 2 ตัวนี้แหละจะถูก Pointer ในบรรทัดที่ 22 ชี้

บรรทัดที่ 26:เป็นการให้ Pointer ชี้ไปที่ Object Pg และในบรรทัดที่ 27 ก็เป็นการสั่งให้ทำ Function WriteProgram

บรรทัดที่ 31:เป็นการให้ Pointer ชี้ไปที่ Object Db และในบรรทัดที่ 31 ก็เป็นการสั่งให้ทำ Function WriteProgram

 จาก Output จะเห็นได้ว่า โปรแกรมนี้เราได้มีการใช้ Function WriteProgram 2 ครั้ง ซึ่งการทำงานที่ได้จะไม่เหมือนกันขึ้นอยู่กับว่า Pointer ชี้ไปที่ Object ที่มาจาก class แม่ หรือ class ลูก 

โปรแกรมที่ 13-2 แสดงตัวอย่างการใช้ Polymorphisam

Source code

1:#include"iostream.h"

2:class Point

3:{

4: public:

5: virtual void Paint()

6: {

7: cout << "*";

8: }

9:};

10:class Square:public Point

11:{

12: public:

13: void Paint()

14: {

15: cout << "*****" << endl;

16: cout << "*****" << endl;

17: cout << "*****" << endl;

18: cout << "*****" << endl;

19: cout << "*****" ;

20: }

21:};

22:class Triangle:public Point

23:{

24: public:

25: void Paint()

26: {

27: cout << " * " << endl;

28: cout << " * * " << endl;

29: cout << " * * " << endl;

30: cout << "*******" ;

31:

32: }

33:};

34:

35:int main()

36:{

37: Point *Poi;

38: Point Po;

39: Square Sq;

40: Triangle Tri;

41:

42: cout << "Point to Object of Point class." << endl;

43: Poi = &Po;

44: Poi->Paint();

45:

46: cout << endl << endl;

47: cout << "Point to Object of Square class." << endl;

48: Poi = &Sq;

49: Poi->Paint();

50:

51: cout << endl << endl;

52: cout << "Point to Object of Triangle class." << endl;

53: Poi = &Tri;

54: Poi->Paint();

55:

56: return 0;

57:}

Output ดังรูปที่ 13-1

 รูปที่ 13-1 แสดง Output ของ โปรแกรมที่ 13-2

อธิบาย Source code

 โปรแกรมนี้มี class อยู่ 3 class คือ Point เป็น class แม่ของ Square และ Triangle ทั้ง 3 class นี้ใช้ virtual Function ชื่อ Paint

บรรทัดที่ 37:เป็นการสร้าง Pointer ประเภท Point

บรรทัดที่ 38 ถึง บรรทัดที่ 40:เป็นการสร้าง Object ของ class Point,Square และ Triangle ตามลำดับ

บรรทัดที่ 43 ถึง บรรทัดที่ 54:จะเป็นการให้ Pointer ชี้ไปที่ Object ต่างๆ และใช้ Function Paint ซึ่งจะเห็นได้ว่า การทำงานจะไม่เหมือนกัน ขึ้นอยู่กับว่า Pointer ชี้ไปที่ Object ของ class ใด

การใช้ Object ที่เป็น array ร่วมกับ Polymorphism

 ถ้าหากเราจะใช้ Polymorphism โดยการใช้ Pointer ชี้ไปที่ Object ต่างๆ เราก็สามารถสร้าง Object ที่เป็น array จาก class ลูกหลายๆ คลาส และให้ Pointer ชี้ไปที่ Object ที่ต้องการได้ โดยที่เราจะใช้ Member Function ผ่าน Pointer ตัวเดียวแทนที่จะต้องใช้ของ Object เช่นถ้าหากเรามี class อยู่ 3 class

class Programmer

{

 private:

 int Age;

 public:

 virtual void WriteProgram()

 {

 cout << "Write Program";

 }

 void SetAge(int Num1)

 {

 Age = Num1;

 }

 int GetAge()

 {

 return Age;

 }

};

 

class DatabaseProgrammer:public Programmer

{

 public:

 void WriteProgram()

 {

 cout << "Write Database Program";

 }

};

 

class NetworkProgrammer:public Programmer

{

 public:

 void WriteProgram()

 {

 cout << "Write Network Program";

 }

};

  แล้วเราสร้าง Pointer ที่จะชี้ไปที่ Object ดังนี้

 Programmer *Poi;

 จากนั้นก็ให้เราสร้าง Object ที่เป็น array ของ แต่ละ class เช่น

 Programmer Pg[3];

 DatabaseProgrammer Db[3];

 NetworkProgrammer Nw[3];

 เวลาที่เราต้องการใช้ Object ไหนก็ให้เราใช้ Pointer ชี้ไปที่ Object นั้นก่อนจากนั้นก็ให้ใช้ Object นั้นผ่าน Pointer เช่น

 Poi = &Pg[0];

 Poi->SetAge(30);

 cout << Poi->GetAge();

 Poi = &Db[1];

 Poi->SetAge(10);

 Poi->WriteProgram();

 จากตัวอย่างนี้จะเห็นได้ว่าเราได้ใช้ Pointer ในการควบคุมการทำงานของของ Object 2 Object คือ Pg[0] และ Db[1];

โปรแกรมที่ 13-3 ตัวอย่างการใช้ Object ที่เป็น array ร่วมกับ Polymorphism

1:#include"iostream.h"

2:class Programmer

3:{

4: private:

5: int Age;

6: public:

7: virtual void WriteProgram()

8: {

9: cout << "Write Program";

10: }

11: void SetAge(int Num1)

12: {

13: Age = Num1;

14: }

15: int GetAge()

16: {

17: return Age;

18: }

19:};

20:

21:class DatabaseProgrammer:public Programmer

22:{

23: public:

24: void WriteProgram()

25: {

26: cout << "Write Database Program";

27: }

28:};

29:

30:class NetworkProgrammer:public Programmer

31:{

32: public:

33: void WriteProgram()

34: {

35: cout << "Write Network Program";

36: }

37:};

38:

39:

40:int main()

41:{

42: Programmer *Poi;

43: Programmer Pg[3];

44: DatabaseProgrammer Db[3];

45: NetworkProgrammer Nw[3];

46:

47: Poi = &Pg[0];

48: Poi->SetAge(40);

49: cout << "Age of Programmer 1 is:" << Poi->GetAge() << endl;

50:

51: Poi++;

52: Poi->SetAge(50);

53: cout << "Age of Programmer 2 is:" << Poi->GetAge() << endl;

54:

55: Poi = &Db[1];

56: Poi->SetAge(30);

57: cout << "Age of DatabaseProgrammer 1 is:" << Poi->GetAge() << endl;

58:

59: Poi = &Nw[0];

60: Poi->SetAge(20);

61: cout << "Age of NetworkProgrammer 1 is:" << Poi->GetAge() << endl;

62:

63: Poi++;

64: Poi->SetAge(25);

65: cout << "Age of NetworkProgrammer 2 is:" << Poi->GetAge() << endl;

66:

67:

68: return 0;

69:}

Output

Age of Programmer 1 is :40

Age of Programmer 2 is :50

Age of DatabaseProgrammer 1 is :30

Age of NetworkProgrammer 1 is :20

Age of NetworkProgrammer 2 is :25

อธิบาย Source code

 โปรแกรมนี้ได้มีการใช้ Pointer ให้ชี้ไปที่ Object หลายๆ Object และในโปรแกรมนี้เราได้กำหนด Object ให้เป็น array ด้วย

บรรทัดที่ 42:เป็นการสร้าง Pointer และบรรทัดที่ 43,44,45 เป็นการสร้าง Object จาก class ต่างๆ ให้เป็น array

บรรทัดที่ 47:เป็นการให้ Pointer ชี้ไปที่ Object Pg อินเด็กซ์ที่ 0

บรรทัดที่ 51:เป็นการใช้ โอเปอเรเตอร์ ++ กับ Pointer ซึ่งถ้าหาก Pointer ชี้ไปที่ Object ที่เป็น array อยู่ Pointer ก็จะทำการชี้ไปที่ index ต่อไป  ในที่นี้ Pointer จะชี้ไปที่ Object Pg อินเด็กซ์ที่ 1

 จากนี้ไปจนถึงจบโปรแกรมก็จะเป็นการทำงานคล้ายๆ แบบนี้ จะเห็นได้ว่าเราใช้ Pointer ตัวเดียวในการจัดการกับ Object ได้หลายตัว โดยที่ Object นั้นไม่จำเป็นต้องเป็นประเภทเดียวกันด้วย

Constructor และ Destructor ใน Polymorphism

 ถ้าเราจะใช้ Polymorphism เราต้องทำการ Inheritance ก่อน Constructor และ Destructor ใน Polymorphism จึงเหมือนกัย Inheritance คือ เมื่อมีการสร้าง Object ก็จะทำ Constructor และเมื่อเลิกใช้ Object ก็จะทำ Destructor

 ส่วนในการที่เราให้ Pointer ชี้ไปที่ Object ต่างๆ นั้นเป็นการชี้ ไม่ได้เป็นการสร้าง Object ขึ้นมาใหม่ เพราะฉะนั้น Constructor และ Destructor ก็จะไม่ทำงานเมื่อมีการให้ Pointer ชี้ไปที่ Object

โปรแกรมที่ 12-4 ทดสอบ Constructor และ Destructor ใน polymorphism

Source code

1:#include"iostream.h"

2:class Programmer

3:{

4: private:

5: int Age;

6: public:

7: virtual void WriteProgram()

8: {

9: cout << "Write Program";

10: }

11: void SetAge(int Num1)

12: {

13: Age = Num1;

14: }

15: int GetAge()

16: {

17: return Age;

18: }

19: Programmer()

20: {

21: cout << "Programmer Constructor " << endl;

22: }

23: ~Programmer()

24: {

25: cout << "Programmer Destructor " << endl;

26: }

27:};

28:

29:class DatabaseProgrammer:public Programmer

30:{

31: public:

32: void WriteProgram()

33: {

34: cout << "Write Database Program";

35: }

36: DatabaseProgrammer()

37: {

38: cout << "DatabaseProgramer Constructor " << endl;

39: }

40: ~DatabaseProgrammer()

41: {

42: cout << "DatabaseProgramer Desstructor " << endl;

43: }

44:};

45:

46:class NetworkProgrammer:public Programmer

47:{

48: public:

49: void WriteProgram()

50: {

51: cout << "Write Network Program";

52: }

53: NetworkProgramer()

54: {

55: cout << "NetworkProgramer Constructor " << endl;

56: }

57: ~NetworkProgrammer()

58: {

59: cout << "NetworkProgramer Destructor " << endl;

60: }

61:};

62:

63:int main()

64:{

65: cout << "Create Programer *Poi" << endl;

66: Programmer *Poi;

67:

68: cout << endl << "Create Programmer Pg" << endl;

69: Programmer Pg;

70:

71: cout << endl << "Create DatabaseProgrammer Db" << endl;

72: DatabaseProgrammer Db;

73:

74: cout << endl << "Create NetworkProgrammer Nw" << endl;

75: NetworkProgrammer Nw;

76:

77: Poi = &Pg;

78: Poi = &Db;

79: Poi = &Nw;

80:

81: cout << endl << endl;

82:

83: return 0;

84:}

Output

Create Programmer *Poi

 

Create Programmer Pg

Programmer Constructor

 

Create DatabaseProgrammer Db

Programmer Constructor

DatabaseProgrammer Constructor

 

Create NetworkProgrammer Nw

Programmer Constructor

 

 

NetworkProgrammer Destructor

Programmer Destructor

DatabaseProgrammer Destructor

Programmer Destructor

Programmer Destructor

อธิบาย Source code

 โปรแกรมนี้ได้มีการทดสอบ Constructor และ Destructor ในการ Polymorphism ซึ่งจะเห็นได้ว่า

เหมือนกับการ Inheritance  คือเมื่อมีการสร้าง Object  Object นั้นก็จะทำ Constructor แต่ในการที่เราให้ Pointer ชี้ไปที่ Object จะไม่มีการทำ Constructor