Sultan_Althibity

كائنات السي بلس بلس (مجموعة دروس)

51 ردود في هذا الموضوع

لمن هذه الدروس:

هذه الدروس لكل من يريد تعلم البرمجـة الكائنيـة أو تعلمها ولم يفهـم فلسفتها بشكل عـميق للغاية وهي أيضاً لكل من أتقن لغـة السي ويريد تعلم لغـة السي بلس بلس.

مواضيع هذه الدروس:هذه الدروس تهتم بكيفية صقل إمكاناتك في البرمجـة الكائنية أو الشيئيـة أو الغرضية الهـدف.

تسلسل هذه الدروس:هذه الدروس تبدأ بمراجعـة بسيطة حول الـ struct في لغـة السي ثم تتقدم شيئاً فشيئاً حتى تصل إلى مرحلة متقدمـة من البرمجـة الكائنيـة وسأحاول فيها شرح المبادئ الثلاث للبرمجـة الكائنية.

زمن هذه الدروس:

سأحاول إضافة درس كل يومين أو ثلاثـة أيام أو أربعـة أيام كأقصى حـد

سبب وضع هذه الدروس:أنا إنسان لا أحب دوال الـ API ، لذلك أردت الانتقال إلى صفوف مايكروسوفت التأسيسيـة MFC بدون أن أتعلم مبادئ البرمجـة الكائنية ، وبالرغـم من أني أستطعت بناء تطبيقات بسيطـة بواسطـة الفيجوال سي6 ، إلا أني لم أستطع كتابة أكـواد أو ربما استطعت ولكن على نسق أمثلة كانت متوفرة عـندي والأمر كلـه إعادة إختراع فقط ، لذلك رجعت إلى الكونسول وفهـمت الكائنات في السي بلس بلس وهأنا ذا ، أترك الفيجوال سي بلس بلس ، والسي بلس بلس برمتها وانتقل إلى الفيجوال سي شارب دوت نت ، ولكن هذه المرة بشكل أكثر ثقـة من السابق........ أردت أن أنقل تجربتي إلى بقية المبتدئين وأرجـو منهـم ألا يتعلموا طريقة البرمجـة الكائنية من أستاذ يقول لهـم هـكذا نستخدمها ، بل على أستاذ يقول ، هذه هي فائدتها أو هذه هي فلسفتها .........

سأبدأ أولاً من أفضل شيء تقدمـه لك لغـة السي وهي التراكيب ... قد يصل عـدد دروس هذا الموضوع إلى عشرة دروس فقط ... ولكن أعـدكم بأن تكون غـنية ...

أرجـو منكم في النهاية التفاعل معـي وتصحيح أخطائي إن وجدت ... وأرجــو ألا يقوم أحد بتجميع الدروس في ملف وورد أو بي دي إف ... فأنا من سيقوم بهذه المهـمـة في النهاية

سأضيف الدرس الأول بعـد خمس دقائق ، حيث أني حالياً أقوم بتنسيقـه

تم تعديل بواسطه عماد الخليل
1

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

بسم الله الرحمن الرحيم

الدرس الأول

التراكيب في لغـة السي بلس بلس

Structures In C++ Languge

هذا هـو أول درس جدي في هذه السلسلة كل ما أطلبه منك هـو التركيز جيداً ، وتذكر أن هذه المادة لا ينفع معها القراءة السريعـة بل القراءة المتأنية....

الكائن عبارة عـن رزمـة ، قد تتساءل ما هي مكونات هذه الرزمـة ، هذه الرزمـة مكونـة من دوال ومتغيرات تندرج تحت هذا الكائن...

تحاول البرمجـة الكائنية تقليد الواقع العـملي لذلك عليك التفكير بها من هذه الناحيـة، كما تعلم فإن كل شيء في هذه الحياة عبارة عـن كائن ، مثل الإنسان أو الحيوان أو أي شيء آخر ، من هذا المنطلق لنأخذ مثلاً من الحياة العـملية ، وهـو كائن الطالب ، كائن الطالب عبارة أولاً عـن إنسان وبالتالي فهـو يحوي جميع خصائص الإنسان ، لننظر إلى كائن الطالب من ناحية برمجية كائنية ، لن نقول أولاً أن كائن الطالب عبارة عـن إنسان ، لأننا أولاً لن نستطيع كتابة جميع ما يقوم به الإنسان في برنامج بل سنهتم بالناحية التي تهـمنا كمبرمجين أو إلى احتياجات البرنامج الذي نقوم بكتابته ، سننظر إلى كائن الطالب أنه عبارة عـن مجموعـة من المواد وكل مادة مكونـة من درجـة وأنه مكوّن أيضاً من اسمه الرباعي ورقمـه التسلسلي .... أنظر إلى كيف سنكتب صنف الطالب في لغـة السي:

1.	struct student {
2. char itsName[200];
3. int itsNumber;
4. float gradesOfCourses[5];
5. int itsAvg;
6. };

حسناً لنقل أنك تقوم بكتابة برنامج يقوم بحساب مجموع درجات الطالب ، ويوجد معـدل الطالب من 4 ، أنظر إلى هذا البرنامج بشكل كامل، وسننتقل الآن إلى البرمجـة بلغـة السي بلس بلس وليس السي:

1.	#include <iostream>
2. using namespace std;
3.
4. struct student {
5. char itsName[200];
6. int itsNumber;
7. float gradesOfCourses[5];
8. float itsAvg;
9. }
10.;
11. int main()
12. {
13.  student Ahmed;
14.  for(int i = 0;i < 5;i++) {
15.   cout << "Enter the grade of course" << i+1 << ":\t";
16.   cin >> Ahmed.gradesOfCourses[i];
17.  }
18.  int total=0;
19.  for( i=0; i< 5;i++)
20.   total+=Ahmed.gradesOfCourses[i];
21.
22.  int avg=total/ 5;
23.
24.  Ahmed.itsAvg = (avg*4) /100;
25.  cout << Ahmed.itsAvg << endl;
26.
27.  return 0;
28. }

لن أشرح لك هذا الكـود فهـو بسيط ، ولكن لنفرض أنك قررت زيادة عـدد مواد الطالب إلى 10 ، وليس ذلك فحسب بل قررت أيضاً حساب المعـدل بالنسبة المئويـة:

1.	#include <iostream>
2. using namespace std;
3.
4. struct student {
5. char itsName[200];
6. int itsNumber;
7. float gradesOfCourses[10];  /*  يوجد تغيير في حجم المصفوفة  */
8. float itsAvg;
9. }
10.;
11. int main()
12. {
13.  student Ahmed;
14.  for(int i = 0;i < 10;i++) { /*  يوجد تغيير في شرط الحلقة  */
15.   cout << "Enter the grade of course" << i+1 << ":\t";
16.   cin >> Ahmed.gradesOfCourses[i];
17.  }
18.  int total=0;
19.  for( i=0; i< 10;i++)    /* يوجد تغيير في شرط الحلقة  */
20.   total+=Ahmed.gradesOfCourses[i];
21.
22.  float avg=total/ 10; /*  يوجد تغيير في المقسوم عليه  */
23.
24.  Ahmed.itsAvg = avg;   /*  يوجـد تغيير كامل في طريقة حساب المعـدل  */
25.  cout << Ahmed.itsAvg << endl;
26.
27.  return 0;
28. }

قد ترى التعـديلات التي قمت بها بسيطـة ولكن بعـد بسيط فإن التعـديلات التي قمت بها هي خمس تعـديلات ؛ قد ترى الأمر بسيطاً للغاية ، ولكن ماذا لو كان الأمر أكثر من ذلك بكثير ؛ ماذا لو طلب منك مثلاً جعل حجم مواد الطلاب ديناميكي وليس ثابت ، أيضاً لقد قمت بخمس تعـديلات على تركيب struct لا يتجاوز حجم أسطره عـن خمسة أسطر ؛ ماذا لو كان أكبر من ذلك بكثير ... إذا ما هـو الحل برأيك؟ ؛ الحل الذي تريده أنت الآن هـو أن تجعل التركيب student ، يقوم بتعـديل المعـدل أو المتغير itsAvg ، حسب الطلب ؛ وليس أن تقوم أنت بتغيير المعـدل كلما أردت فعل ذلك...

الحل المثالي الذي ستقوم بـه ؛ هـو إضافة دالة عضو جـديدة تقوم بحساب المعـدل من أي رقم تريده من 100 أو من 1000 أو من 5 أو من أي رقم آخر ؛ قد تستغرب إضافة دالة إلى تركيب لتصبح عضواً فيه مثل أي عضو متغير ، في السي بلس بلس هذا الأمر مسموح ، لكن في لغـة السي غير مسموح ، أنظر الآن إلى التعـديلات التي أجرينها على التركيب student :

1.	struct student {
2. char itsName[200];
3. int itsNumber;
4. float gradesOfCourses[10];
5. float itsAvg;
6. void CalculatorOfAvg(int = 100);
7. };
8.
9. void student::CalculatorOfAvg(int m)
10. {
11.  for(int i = 0;i < 10;i++) {
12.   cout << "Enter the grade of course" << i+1 << ":\t";
13.   cin >> gradesOfCourses[i];
14.  }
15.  float total=0;
16.  for( i=0; i< 10;i++)
17.   total+=gradesOfCourses[i];
18.
19.  int avg=total/ 10;
20.
21.  itsAvg = (avg*m) /100;
22. }

أنظر إلى السطر السادس ألا تجـد أني قمت بإضافة دالة اسمها CalculatorOfAvg ، هذه الدالة تقوم بحساب المعـدل الجامعـي بناءً على البارامتر الممرر إليها ؛ إذا لم يمرر المستخدم إليها شيئاً فستقوم افتراضياً بحساب المعـدل الجامعي من 100 .

الآن أنظر إلى الدالة main والتي سنستخدمها لحساب المعـدل مثلاً من 10 ؛ أنظر ولاحظ الفرق بينها وبين الأكواد السابقة:

1.	int main()
2. {
3.  student Ahmed;
4.  Ahmed.CalculatorOfAvg(4);
5.  cout << Ahmed.itsAvg << endl;
6.  return 0;
7. }

قد تقول مثلاً أن الأسطر التي كانت موجودة في الدالة main والتي تقوم بحساب المعـدل الجامعي قد قمت بإضافتها إلى التركيب struct في الدالة CalculatorOfAvg ، وأن كل ما قمت به هـو أنك رفعت أسطر من مكان ووضعتها في مكان آخر ...

حسناً كل ما تقوله صحيح ، ولكن الفرق بين الطريقة التقليدية وهذه الطريقة الجـديدة ، هـي أني أرحت نفسي من عـناء التفكير في أمور المعالجـة وكيفية حساب المعـدل الجامعي ، أيضاً أرحت من سيأتي من بعـدي ممن يريد استخدام التركيب الذي صنعتـه من قراءته كله ؛ فيكفيه أن يرى الدالة CalculatorOfAvg حتى يعرف ما تقوم به وبالتالي يريح نفسه من عـناء التفكير في قضية حساب المعـدل الجامعـي ...

الخلاصـة:

لقد انتهى الدرس الأول .. وأتمنى منك إعادة قراءتـه فهـو مهـم لمن لا يعرف الفائدة القصوى التي تقدمها البرمجـة الكائنية ، والفرق بينها وبين البرمجـة الإجرائية أو الهيكلية ، لقد تعلمت الفرق بين الـ struct في لغـة السي والـ struct في لغـة السي بلس بلس ، وتعلمت أيضاً ولو بتلميح بسيط للغاية كيف تقوم بالفصل بين المعالجـة والواجهـة وكيف اختصرت الكثير من الجهـد حينما أضفت الدالة CalculatorOfAvg .

تم تعديل بواسطه hasan_aljudy
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

ِشكرا لك أخي الكريم..هكذا سنتكامل..

الأخ الشمري في Api و أنت في MFC ^.^

وشكرا

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

ربما سأضيف مكتبات MFC في آخر هذا الموضوع (بعـد 10 إلى 15 درساً) ربما

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

شكراً يأخ = ((vector))

ملحوظة بسيطة :-

تستطيع تغيير كلمة struct إلى class كلاهما تأديان نفس الغرض في لغة ++C

struct في لغة السي وتستطيع أن تعمل بها في ++C

class في لغة ++C ولا تستطيع أن تعمل بها في C

تم تعديل بواسطه الممتاز
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

توضيح بسيط للاخوة أيضا الفرق بين الclass and struct

الclass الdefault is private but in the struct the default is public

ممكن الstruct يشيل دوال ولكن ليس من المستحب عمل ذلك حتى لا يكون vaiolation of oop يعنى إنتهاك لحقوق الoop وبالتالى فى تلك الحالة يفضل إستخدام الclasses

وشكرا لكم

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

إخـوتي الأعزاء .... جميع ما قلته سأتناولـه في الدروس المقبلـة فلم العـجلة .....

أنا وضعت الـ struct حتى يعتاد المبتدئ في البرمجـة الكائنية عليها ... وخاصـة أن أغلبهـم من لغات السي ......

لماذا لا تركزون على الفكرة التي أردت إيضاحها في الدرس الأول .... وهي برمجـة الواجهـات وليس المعالجـة ..

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

شكرا لك مفيد جدا

.. واتمنى معرفة كيفية عمل الواجهة بـ MFC

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

بارك الله فيك على هذه الدروس اخ vector

يا اخوان .. رجاءا لا تقفزوا على الموضوع ولا تستبقوا الاحداث .. دعو الدروس تسير.

فيما يخص الاخوان اللذين سألوا عن MFC, فاعتقد (و هذا ما فهمت من كلام الاخ vector) ان هذه الدروس ليست للـ MFC بل للـ OOP.

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

=========================

الدرس الثاني

التراكيب في لغـة السي بلس بلس (2)

Structures In C++

ما زلنا بعـد في موضوع التراكيب ؛ الذي أريده الآن منك أن تعرف الفرق بين التركيب والمتغير من نفس نمط التركيب وهـناك مواضيع كثيرة يجب عليك فهـمها....

الفرق بين التراكيب والمتغيرات:

أنظر الآن إلى تركيب الطالب الذي قمنا بكتابتـه في الدرس الأول:

1.	struct student {
2. char itsName[200];
3. int itsNumber;
4. float gradesOfCourses[10];
5. float itsAvg;
6. void CalculatorOfAvg (int = 100);
7. };

الآن أنظر إلى هذا السطر:

student Ahmed;

هل تعرف الآن ما هـو الفرق بين الكودين .

هل قام الكود الأول بأي حجز للذاكرة ، هل سيقوم المترجم في الكـود الأول بإنشاء صنف أو تركيب اسمـه student وحجز ذاكرة له.... الجواب هـو لأ ؛ لن يكون هـناك أي حجز للذاكرة في الكـود الأول ، كل ما ستقوم بـه هـو إعلام المترجم بأن هـناك صنف أو تركيب جـديد هـو student .... وبالتالي فحينما تقوم بكتابة الكود الثاني فلن يقوم المترجم بإصدار أي خطأ ، الكود الثاني يقوم بحجز للذاكرة ، حيث يقوم بإنشاء متغير أو كائن (سمه ما شئت ) تحت اسم Ahmed ويحجز له الذاكرة التي تشغلها النـوع أو النمط أو الصنف (سمـه ما شئت ) وهـو student .

* دالة البناء:تعلمت في الفقرة السابقـة ما هـو الفرق بين البنيـة struct والمتغيرات المعرفة من نفس نمطها ، وتعرفت في الفقرة السابقـة على بنيـة أو صنف الطالب ؛ ما رأيك الآن أن نقوم بتطوير صنف الطالب ليصبح أكثر فاعلية ؛ هل تتذكر كيف أضفنا الدالة CalculatorOfAvg ، وكيف أراحتنا من عـناء الكتابة في الدالة main ؛ ما رأيك الآن أن نجعل البنية student تستطيع من خلالها تغيير عدد مواد الطالب ؛ تستطيع ذلك إذا نظرنا للأمر من ناحية إجرائيـة ولكن دعـنا ننظر إلى الأمر من ناحية كائنية ، البنية student يجب أن تكون مستقلة عـن التغييرات الخارجيـة ، لنفترض أن أحد المبرمجين طلب منك كتابة بنيـة أو تركيب اسمها student ، وطلب منك أن لا يكون لها مثيل ، عليك الآن أن تجعل التركيب مريحاً للغاية للمبرمج الذي طلب منك إنشاءه ؛ فمثلاً لو أردنا تغيير عـدد المواد ، الآن إما أن تقوم بهذه المهـمـة بنفسك أو تجعلها للمبرمج الآخر ؛ من الأفضل أن تقوم بها بنفسك فمن الممكن أن يكون المبرمج الآخر هـو رئيسك في العـمل ؛ دعـنا الآن نرجع إلى مهـمـة تغيير عـدد المواد ، أي المطلوب منك الآن أن تجعل المصفوفة العضو في التركيب student مصفوفة ديناميكيـة ، ومن الأفضل أن تقوم بكتابة متغير جـديد هـو عـدد المواد ، أنظر إلى النسخـة الثانية من التركيب student :

1.	struct student {
2. char itsName[200];
3. int itsNumber;
4. float* gradesOfCourses; /* هذا هـو التغيير الأول حيث سنقوم بالتحويل إلى مصفوفة ديناميكة */
5. float itsAvg;
6. void CalculatorOfAvg (int = 100);
7. int NumberOfCourses;   /*  هذا هـو التغيير الثاني حيث وضعـنا متغير لعـدد المواد  */
8. };

هـناك تغييرين فقط ، الآن دعـنا نقرر هل نترك مهـمـة تعيين أو حجز الذاكرة للمصفوفة الديناميكية gradesOfCourses للمبرمج الذي طلب منا القيام ببرمجـة هذا التركيب أو نحن من سنقوم به ؛ من الأفضل أن نقوم به نحن ؛ فالبرمجـة الكائنية تقول لك دائماً إذا قمت بكتابة أي كائن أو تركيب فلا تتركـه حتى يكون كاملاً ومستقلاً وحتى يصبح لا يحتاج للتغيير من المبرمجين الآخرين ؛ ماذا سنفعل الآن وكيف سنحجز الذاكرة للمؤشر gradesOfCourses ؛ إليك الجواب سنقوم بكتابة دالة بناء ؛ ما هي دالة البناء ؟ ؛ دالة البناء هي التي تقوم ببناء التركيب أو الكائن وتحجز له الذاكرة ، كيف نكتب دالة البناء ، دالة البناء تحمل نفس اسم التركيب الذي ستقوم ببناءه ، وهي لا تعيد أية قيمـة وبإمكانها استقبال وسائط أو بارامترات ، دعـنا الآن نقرر كيف سنقوم بكتابة دالة البناء ، على دالة البناء أن تقوم بتهيئـة المتغير NumberOfCourses بعـدد المواد المطلوبة ، وعليها أيضاً أن تحجز الذاكرة للمؤشر gradesOfCourses ، أنظر الآن إلى تركيب student بحلته الجـديدة:

1.	struct student {
2. student (int )  /*   هذه هي دالة البناء  */
3. char itsName[200];
4. int itsNumber;
5. float* gradesOfCourses;
6. float itsAvg;
7. void CalculatorOfAvg (int = 100);
8. int NumberOfCourses;  
9. };

ليس هـناك إلا تغيير وحيد فحسب ، وهـو إضافة دالة البناء في السطر الثاني ؛ أنظر إلى تعريف دالة البناء :

1.	student::student (int a ): NumberOfCourses(a)
2. {
3. gradesOfCourses = new float [NumberOfCourses];
4. }

لقد قمت الآن بتعـديل عـدد مواد الطالب ؛ سينتج عـن هذا التعـديل تعـديلات أخرى في التركيب student ، على العـموم سأكتب البرنامج كله وركز الآن إلى كيفية استخدام الدالة main( ) ، وكيف سنستخدم دالة البناء من خلالها ، وأيضاً إلى التعـديلات الجديدة:

1.	#include <iostream>
2. using namespace std;
3.
4.
5. struct student {
6. student(int);
7. char itsName[200];
8. int itsNumber;
9. float* gradesOfCourses;
10. float itsAvg;
11. void CalculatorOfAvg(int = 100);
12. int NumberOfCourses;
13. };
14.
15. student::student (int a ): NumberOfCourses(a)
16. {
17. gradesOfCourses = new float [NumberOfCourses];
18. }
19.
20.
21. void student::CalculatorOfAvg(int m)
22. {
23.  for(int i = 0;i < NumberOfCourses;i++) {
24.   cout << "Enter the grade of course" << i+1 << ":\t";
25.   cin >> gradesOfCourses[i];
26.  }
27.  float total=0;
28.  for( i=0; i< NumberOfCourses;i++)
29.   total+=gradesOfCourses[i];
30.
31.  int avg=total/NumberOfCourses;
32.
33.  itsAvg = (avg*m) /100;
34. }
35.
36. int main()
37. {
38.  cout << "Enter The Number Of Courses\n";
39.  int i=0;
40.  cin >> i;
41.  student TheStudent(i);
42.  cout << "Enter The Avg u want to calcualtor\n";
43.  cin >> i;
44.  TheStudent.CalculatorOfAvg(i);
45.  cout << endl << TheStudent.itsAvg << endl;
46.
47.  return 0;
48. }

أنظر إلى السطر 41 وكيف استخدمنا دالة البناء:

41.	student TheStudent(i);

لقد وضعـنا متغير i من النـوع int بين قوسين ، والسبب في ذلك هـو أن أول دالة يقوم المترجم باستدعائها حينما تكون تعـمل على أحد الـتراكيب أو الـ structure ، هـي دالة البناء ؛ الآن لنفرض أنني استبدلت السطر 41 بهذا السطر ؛ فهل سيقوم المترجم بعـملية الترجمـة له:

41.	student TheStudent();

الجواب هـو لأ ؛ والسبب في ذلك عـدم وجود دالة بناء لا تستقبل وسائط ، فدالة البناء الموجودة في السطر 6 من الكـود السابق ، يجب أن تستقبل بارامتراً واحداً ، تستطيع حل هذه المشكلة بجعل هذا البارامتر الوحيد بارامتراً افتراضياً .

لقد انتهينا الآن من دالة البناء ، ويبقى لدينا موضوع أخير هـو دالة الهـدم.

دالة الهـدم هي عكس دالة البناء ، فبدلاً من أن تقوم ببناء التركيب أو الصنف فإنها تقوم بهـدمـه وإلغاء الذاكرة التي تم حجزها ، هذه الدالة تحمل نفس اسم التركيب الذي ستهـدمـه مسبوقاً بهذه العلامـة ( ~ ) ، تذكر أن هذه الدالة لا تعيد أية قيمـة ولا تستقبل أية وسائط.

أنظر الآن إلى شكل التركيب بعـد إضافة دالة الـهـدم إليه:

1.	struct student {
2. student(int);
3. ~student();
4. char itsName[200];
5. int itsNumber;
6. float* gradesOfCourses;
7. float itsAvg;
8. void CalculatorOfAvg(int = 100);
9. int NumberOfCourses;
10. };

حسناً ، هل تعرف الآن ماهي وظيفة دالة الهـدم ، أنظر إلى الأسطر التالية التي سينتج عـنها إحدى المشاكل:

1.	student* a = new student (3);
2. delete a;

لقد تم إنشاء مؤشر وحجز ذاكرة له ، وتم تمرير العـدد 3 ، لدالة البناء ، ولكن أنظر إلى السطر الثاني والذي سيقوم بإلغاء تخصيص الذاكرة، هل هذا يعـني أن العضو المتغير المؤشر gradesOfCourses (وهي مصفوفة حجمها الآن 3 عـناصر) سيتم إلغاؤها ، الجواب هـو لأ ، وعليك الآن القيام بتعريف دالة الهدم التي ستلغي هذا الحجز نهائياً .

هـناك سؤال آخر يجدر بك السؤال عـنه: وهـو متى ستستدعى دالة الهـدم حتى أضمن أنها ستقوم بإلغاء حجز الذاكرة للمؤشر gradesOfCourses ؛ والجواب عـنه هـو أنها ستستدعى عـند انتهاء البرنامج من التنفيذ أو عـند تحرير (إلغاء) الذاكرة لمؤشر من التركيب student ، أي الحالات التي تعـني أن المتغير من نمط التركيب student ينبغـي هـدمـه ؛ أنظر الآن إلى تعريف دالة الهـدم:

1.	student::~student ()
2. {
3. delete [] gradesOfCourses;
4. }

الخلاصـة:

تعلمت في هذا الدرس على الفرق بين التركيب والمتغير الذي يتم تعريفـه على نفس نمط التركيب ، تعرفت على دالتي البناء والهـدم وما هي مميزات الاثنتين والفروق بينهـما ، تعرفت أيضاً على كيفية تغيير عـدد المواد في التركيب student عبر دالة البناء ، وليس عبر الدالة main ؛ الدرسان السابقان ضروريان للغاية إذا ما أردت فهـم الكائنات وما تعـنيه .

تم تعديل بواسطه hasan_aljudy
1

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

سؤال إلى من يريد البدء فوراً بصفوف الـ mfc :

بالرغـم من أني لم أقل أي شيء بخصوص الـ mfc .. ولكن لا أدري لماذا تريدون الانطلاق فوراً بها .. وأنا أعتقد أن غالبيتكم لم يفهـم الفلسفـة وراء الـ OOP وربما حتى مبدأ الكبسلـة لم يفهـم لماذا نستخدمـه وما هي الفائدة ورائـه...

عـندي سؤال وحيد (موجـه فقط للمبتدئيـن) :

لنفرض أن الدكتـور طلب مني كتابة صنف أو نمط بيانات (أعـداد كسريـة) أمام عينيـه هـو، قلت له بسيطـة ، أمسكت الورقـة والقلم (لنفرض أنه لا يوجد لدينا حاسب) وبدأت في كتابة النمط ، فجأة قال لي الدكتـور توقف لقد وقعت في خطأ شنيع ، لم أدري ما هـو الخطأ وأمرني أن أنصرف وقام بترسيبي في المادة بسبب هذا الخطأ (كلها افتراضات وليست حقيقـة) .. إليكم ما كتبت:

class Fraction
{
public:
Fraction ( int = 1 );
};

ما هـو هذا الخطأ ، مع العلـم أنه خطأ تصميمي وليس في قواعـد اللغـة,,,,,,,,,,,,,,,

السؤال فقط للمبتدئين ، لا أريد ممن فهـم فلسفـة الـ OOP أن يجييب ،,,,,,,,,,,

ملاحـظـة : ربما سأضيف الدرس الثالث بعـد ساعـة أو ساعتين وإن لم أتمكن فغـداً

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

اخي الكريم ممكن سؤال ..هل سنطبق هذه الدورس على الكونسول أم Dialog انا أرى مكتبات iostrem ..

انا شخصيا لم أعرف حتى الآن ماهي هذه الoop

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

هذه الدروس على الكونسول وربما نتقدم كثيراً في الـ OOP ، حتى نصل إلى مرحلة الـ mfc ... أقول ربما ولست متأكداً.

ولكن كيف يا أخ eias تريد البرمجـة بمصفوف الـ mfc وأنت بعـد لم تعرف ما هي الـ OOP ... كيف تريد التقدم ... لا تستعـجل ....

لا أري أي إجابات على السؤال الذي طرحتـه حتى نرى إن كنتم جاهزين بالفعل لمكتبات مايكروسوفت التأسيسيـة mfc .

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

الدرس الثالث

الكبسلـة

لقد وصلنا الآن إلى أحد مبادئ البرمجـة الكائنية ؛ وهي الكبسلة أو إخفاء المعلومات( إخفاء المعالجـة)...

قبل كل شيء أريد إيصال فكرة مهـمـة للغاية إليك ؛ هل تتذكر حينما كنت في المدرسـة وابتدأوا بتعليمك مادة قواعـد اللغـة العربية (النحـو) ؛ حسناً لقد قالوا لك أن المبتدأ في الجملة الاسمية يجب أن يكون مرفوعاً دائما ؛ مثل الجملة: البرمجـة شيء رائع ؛ هل قالوا لك السبب ؛ أو دعـني أصيغ السؤال بطريقة أفضل : هل من الضروري أن تعرف السبب ؛ الجواب لا يحتاج أن تعرف السبب إلا إن أردت أن تكون متخصصاً بعلم النحـو والصرف ؛ لقد كان من الضروري حينما ابتدأوا بتعليمك قواعـد اللغـة العربية في المدرسـة أن يقولوا لك إلتزم دائماً بالقواعـد فالجملة السابقة لا يجوز أن تقوم بتعـديلها إلى ، البرمجـةَ شيئاً رائعٌ (بفتح المبتدأ) ؛ هـنا الأمر ينطبق نفسـه على البرمجـة الكائنيـة ؛ وهذه هي ربما ليست قاعـدة ولكن أعتبر أنها أسلوب برمجي مهـم للغاية (وأشدد على كلمـة مهـم) :

كل ما هـو ليس ضرورياً أن يصبح واجهـة فعليه أن يكون مخفياً أو عضواً خاصاً ضمن الكائن

قد تقول لماذا هذه القاعدة مهـمـة ؛ دعـك الآن من طرح هذا السؤال فستعرف الفائدة لاحقاً ، وإن كـنت قضيت الدرسين السابقين أحاول أن ألمح إلى هذه القاعـدة ؛ الآن دعـني أدخل في الشرح العـملي لما قلته من كلام نظري.

أنظر إلى تعريف التركيب student :

1.	struct student {
2. student(int);
3. ~student();
4. char itsName[200];
5. int itsNumber;
6. float* gradesOfCourses;
7. float itsAvg;
8. void CalculatorOfAvg(int = 100);
9. int NumberOfCourses;
10. };

دعـنا الآن نقرر من هـو الذي لا نحتـاجـه ونريد أن يصبح مخفياً أو عضواً خاصاً ؛ الجواب وحسب الشكل الحالي للتركيب هـو هؤلاء المتغيرات الأعضاء:

1.	float* gradesOfCourses;
2. float itsAvg;

المتغير في السطر الأول ، فيم تحتـاجـه ، إذا أردت تغيير حجم المواد ، فبإمكانك فعل ذلك عن طريق دالة البناء ، المتغير في السطر الثاني لا تحتاجـه لأن الدالة CalculatorOfAvg ، هي من ستقوم بحساب هذا المتغير Avg ، وليس أنت.

الآن لنأتي إلى الصعيد الكـودي ، كيف نقوم بإخفاء المتغيرين السابقين عـن الواجهـة أو كيف نقوم بجعلها أعضاء خاصـة ؛ الجواب هـو عـن طريق الكلمـة المفتاحية private ؛ أنظر إلى كيفية استخدام هذه الكلمة:

1.	struct NameOfStructure 
2. {
3.  //  هذه الأعضاء أعضاء عامـة
4.  private :  // هذه هي الكلمـة الدليلية التي ستجعل جميع الأعضاء تحتها أعضاء خاصة
5.  //  أكتب هـنا الأعضاء الذين تريد جعلهـم أعضاء خاصـة
6. };

الآن دعـنا نطبق هذه التقنية الجـديدة على التركيب student ؛ أنظر الآن إلى التغيير الحاصل في التصريح عـن هذا التركيب:

1.	struct student {
2. student(int);
3. ~student();
4. char itsName[200];
5. int itsNumber;
6. void CalculatorOfAvg(int = 100);
7. int NumberOfCourses;
8. private:
9. float* gradesOfCourses;
10. float itsAvg;
11. };

أنظر إلى السطر 18 ، الآن كل ما تحت السطر 18 من أعضاء سيصبحـون أعضاء مخفيين أو خاصين داخل التركيب student ...

بعـد أن انتهينا من الصعيد الكـودي ؛ عليك الآن معرفة الفرق بين الأعضاء الخاصـة والأعضاء العامـة ، قم الآن بكتابة هذه الأسطر داخل الدالة main( ) بعـد أن قمنا بتضمين التركيب الجـديد:

1.	student a(10);
2. cout << a.itsAvg;

لن يقوم المترجم بترجمـة السطر 2 ؛ وسيقول لك أن هـناك خطأ ؛ هل تعرف ما هـو الخطأ ؛ إذا رجعت إلى تصريح التركيب student ؛ فستجد أنـه يخبرك أن العضو المتغير itsAvg هـو عضو خاص ؛ هل تعرف الآن ما معـنى عضو خاص ؛ العضو الخاص داخل أي تركيب ، لا يمكن الوصول إليه إلا من خلال التركيب نفسـه .....

قد تتساءل إذاً كيف سيكون بإمكاني طباعـة قيمـة المتغير itsAvg ، وإذا لم أستطع تنفيذ السطر 2 فما هي الفائدة أصلاً من التركيب student ، ألم يكن من الأفضل لو جعلت المتغير itsAvg متغيراً عاماً ؟ .

سؤال دائماً ما يسأله المبتدئون ؛ عـموماً هـناك أسلوب أو قاعـدة برمجية معروفة دائماً وهـي:

إذا قمت بجعل أحد المتغيرات خاصـة فقم فوراً بتوفير محددات الوصول إليها.

محددات الوصول:

ماهي محددات الوصول التي ستحل لي المشكلة السابقـة ، حسناً محددات الوصول هي التي تسمح لك بالوصول إلى المتغيرات الخاصة ، محددات الوصول هي عبارة عـن دالتين ، الدالة الأولى واسمها Get والثانية هـي Set ؛ كيف سأستخدم هذه الدوال؟ ، الجواب هـو أن تقوم بتوفير دالتين الأولى اسمها Get ثم اسم المتغير الخاص ، والثانية اسمها Set ثم اسم المتغير الخاص.

المحدد Get :

أود أن أشير هـنا إلى أنـه ليس هـناك كلمـة دليلية مثل Get و Set ؛ الذي أحدده هـنا هـو أسلوب برمجي متعارف عليه ، وهـو الأفضل ؛ فإذا ما أردت لكائناتك أن تكون مستقرة وقويـة فعليك باعتماد هذا الأسلوب الناجع.

المحدد Get لا يستقبل أي بارامتر ولا يحوي سوى أمر وحيد هـو أمر إعادة المتغير الخاص ، فلنقم الآن بتوفير محدد وصول إلى المتغير itsAvg من التركيب student ، أنظر:

1.	int student::GetitsAvg()const
2. {  return itsAvg; }

وبالتالي فبإمكاننا تعـديل مشكلة الطباعـة في الكود السابق لتصبح هـكذا بعـد التعـديل:

3.	student a(10);
4. cout << a.GetitsAvg();

بالرغـم من أن الأمر يرجع إليك في تحـديد من هـو العضو الخاص والعام ، إلا أن نصيحتي لك هـي أن تقوم بإخفاء جميع المتغيرات كلها وبتوفير محددات الوصول لكل متغير عضو خاص، أعتبر هذا الأمر قاعـدة أو حتى مسلمـة وستعرف لماذا فيم بعـد .... سنطبق هذه المسلمـة على جميع التركيب student ، أنظر الآن إلى الشكل الجـديد للتركيب:

1.	struct student {
2.  student(int);
3.  ~student();
4.  int GetitsNumber()const; /*  يوجد تعـديل هـنا */
5.  int GetNumberOfCourses()const; /* يوجد تعديل هنا */
6.  float GetitsAvg(); /* يوجد تعديل هنا */
7.  float GetgradesOfCourses(int)const; /* يوجد تعـديل هنا */
8.  void CalculatorOfAvg(int = 100);
9.  char itsName[200];
10. private:
11.  float* gradesOfCourses; /* جعلنا هذا المتغير خاص */
12.  float itsAvg; /* جعلنا هذا المتغير خاص */
13.  int NumberOfCourses; /* جعلنا هذا المتغير خاص */
14.  int itsNumber; /* جعلنا هذا المتغير خاص */
15.  };

ل

قد جعلنا جميع المتغيرات الأعضاء خاصـة ، وقمنا بتوفير محدد وصول لكل منها عـن طريق المحدد Get ، لاحظ أن طريقة عـمل هذا المحدد تختلف بالنسبة للمؤشر gradesOfCourses لاحظ أيضاً أننا لم نقـم بتوفير محدد وصول Get للمصفوفة الحرفية itsName ، والسبب في ذلك هـو طبيعـة هذه المصفوفة أي أن الأمر صعوبات كـودية فقط وليست تصميميـة ، ومن الآن فلاحقاً سيتم حذف هذه المصفوفة من هذا التركيب ، وربما سنستبدلها بإحدى المتغيرات string ، إذا وصلنا إلى تلك المرحلة المتقدمـة من الدروس...

هـناك ملاحظة مهمـة للغاية وهي أن الدالة get دالة ثابتـة ، احرص دائماً على أن تكون const وإلا فإن أخطاء كثيرة ستظهر دون أن تعرف سببها وخاصـة في المترجمات الجـديدة

المحدد Set :

لنفرض أنك قمت بتسليم هذا التركيب للمبرمج الذي طلبه منك ، وقد أعجب منـه عجباً شديداً للغاية ، ولكنـه أتى إليك في أحد الأوقات ، وقام بتوجيه هذا السؤال أو المشكلة إليك:

لقد حاولت جعل المستخدم يقوم بتغيير درجات مواده بعـد أن ينتهي من كتابتها ، ولكن لا حل لهذه المشكلة ، فالتركيب student لا يقبل السطر الثالث من هذا الكـود:

1.	student a(10)
2. a.CalculatorOfAvg(5);
3. cin >> a.gradesOfCourses[4];

هل تعرف لماذا لا يقبل المترجم السطر الثالث ، السبب كما قلت في نفس هذا الدرس هـو أن المؤشر gradesOfCourses أصبح متغيراً خاصاُ وليس عاماً أي أن الوصول إليه محدد من داخل التركيب وليس من خارجـه.

ما هـو الحل إذاً ؛ الحل هـو أن تقوم بتوفير محدد وصول آخر هـو Set ، هذه الدالة أو المحدد لا تقوم إلا بتعـديل المتغير الذي تصل إليه ، وهي لا تعيد أي قيمـة أي من النـوع void ، ولكنها تستقبل وسيط واحد وحسب ، هـو القيمـة الجـديدة التي تنوي تعـديلها مكان قيمـة المتغير القديمـة ، وأيضاً هـناك قاعـدة جـديدة هي: دائماً إذا قمت بجعل أحد المتغيرات متغيراً خاصاً فعليك بتوفير محدد وصول آخر إليه هـو المحدد Set ، أنظر الآن إلى الشكل الجديد للتركيب:

1.	struct student {
2.  student(int);
3.  ~student();
4.  int GetitsNumber()const;
5.  int GetNumberOfCourses()const;
6.  float GetitsAvg()const;
7.  float GetgradesOfCourses(int)const;
8.  void SetitsNumber(int ); /* يوجد تعـديل هنا */
9.  void SetNumberOfCourses(int); /* يوجد تعـديل هنا */
10. void SetItsAvg(float ); /* يوجد تعـديل هنا */
11. void SetgradesOfCourses(int , float); /* يوجد تعـديل هنا */
12. void CalculatorOfAvg(int = 100);
13. private:
14.  float* gradesOfCourses;
15.  float itsAvg;
16.  int NumberOfCourses;
17.  int itsNumber;
18.  };

هـناك أربع دوال إضافية جديدة لجميع المتغيرات الخاصـة الأربعـة ، سنقوم الآن بكتابة تعريف جميع الدوال ، بالنسبة للدالة الرابعـة والأخيرة فيجب التركيز جيداً عليها لأنها شاذة عـن بقية الدوال ، أنظر:

1.	void student::SetitsNumber(int a) { itsNumber=a;} 
2. void student::SetNumberOfCourses(int a)
3. { NumberOfCourses=a; }
4. void student::SetItsAvg(float a) {itsAvg=a;}
5. void student::SetgradesOfCourses(int d, float a)
6. { gradesOfCourses[d] = a;}

أنظر إلى الدالة في السطر الأول وهـي SetitsNumber ، هذه الدالة تقوم بتغيير قيمـة المتغير العضو itsNumber بالقيمة الجـديدة a أو البارامتر الممرر إليها ، كذلك الأمر بالنسبة للدالة في السطر الثاني والسطر الرابع ، بالنسبة للدالة الرابعـة في السطر الخامس ، فهـي تقوم بحل مشكلـة المبرمج السابق الذي ضربناه كمثل لك في هذا الدرس ، وهـي أنها تقوم بتغيير أي درجـة أدخلها الطالب وعليه فإن هذه الدالة تستقبل بارامترين اثنين ، الأول هـو دليل المصفوفة gradesOfCourses ، أو رقم المادة ضمن المصفوفة ، والبارامتر الثاني هـو القيمـة الجـديدة لذلك العـنصر ضمن المصفوفـة....

لقد انتهيت الآن ، من فهـم محددات الوصول ، لقد قمت بشيء كبير للغاية ، بالرغـم من أنك لا تدرك أهـميته ، لذلك أريد منك أن تنتبه جيداً حتى تفهـم فائدة الكبسلة (أو إخفاء البيانات) لأن هذا الكلام الذي سأكتبه لم أجد كتاباً طوال فترة تعليمي لهذه اللغـة يشرحه بالشكل المطلوب.

لنفترض أنك تعـمل في إحدى الشركات لصناعـة البرمجيات ، وأنه بالفعل طلب منك برمجـة نظام أو برنامج لحساب درجات الطلاب ، وقد قمت بالفعل باستخدام التركيب student الذي استخدمناه في هذا الدرس ، ثم بعـد عـدة سنوات ، طلبت الشركـة التي تعـمل فيها من فريق مبرمجين (لست أنت من ضمنهـم) برمجـة نظام لطلاب الكليات العسكرية ، وقد كلف الفريق أحد المبرمجين بالاعتناء بشؤون الطلاب في هذا النظام ، الذي سيفعله هذا المبرمج أنه سيذهب إلى البرامج السابقـة التي قامت بإنشاءها الشركـة ، ليبحث عـن كائنات (أو تركيبات في هذا المثال) من المفيد أن يستخدمها في نظامها ، وقد اختار هذا المبرمج التركيب الذي قمت أنت بكتابته قبل ثلاث سنوات ، أنظر ماذا سيفعله هذا المبرمج ، هذا المبرمج وجميع المبرمجين الآخرين لن ينظر إلى كامل التركيب الذي قمت بإنشاءه بل إلى واجهـة التركيب ، لن ينظر إلى تعريفات الدوال أو المتغيرات أو بمعـنى أصح لن ينظر إلى كيف عالجت هذا التركيب، أي أن المبرمج سينظر إلى هذا الجزء من التركيب student :

19.	struct student {
20. student(int);
21. ~student();
22. int GetitsNumber()const;
23. int GetNumberOfCourses()const;
24. float GetitsAvg()const;
25. float GetgradesOfCourses(int)const;
26. void SetitsNumber(int );
27. void SetNumberOfCourses(int);
28. void SetItsAvg(float ); void SetgradesOfCourses(int , float);
29. void CalculatorOfAvg(int = 100);
30. private:
31.  float* gradesOfCourses;
32.  float itsAvg;
33.  int NumberOfCourses;
34.  int itsNumber;
35.  };

الآن أود أن أشير هـنا إلى قاعـدة مهـمـة للغاية:

المبرمجـون الذين يفكرون بطريقة كائنية يقومون ببرمجـة الواجهـة وليس المعالجـة.

أي أن هذا المبرمج الذي ينظر إلى تركيبك لن يفكر أبداً بكيفية معالجتك لحساب الدرجات ، فحسب الواجهـة للتركيب الذي قمت أنت بإنشاءه فإنك تقول لمن يريد أن يستخدم تركيبك: إذا أردت حساب معدل الدرجات ، فعليك باستخدام الدالة CalculatorOfAvg ، وقم بتمرير الدرجـة النهائية إلى هذا الدالة ، وتقول أيضاً حسب الواجهـة ، إذا أردت معرفة درجـة أي مادة حصل عليها الطالب ، فعليك باستخدام الدالة GetgradesOfCourses ، مع تمرير رقم المادة إلى الدالة...

لنفرض الآن أنك قلت لنفسك قبل قراءة أي درس من هذه الدروس أني لست بحاجـة للبرمجـة الكائنية وأني أستطيع فعل ما أريد دون الحاجـة إلى هذه التفاهات ، أنظر إلى تركيب student بلغـة السي:

1.	struct student {
2. float* gradesOfCourses;
3. float itsAvg;
4. int NumberOfCourses;
5. int itsNumber;
6. };

هل تعرف الآن ماذا سيفعله المبرمج الذي ظل يبحث عـن تركيب للطلاب ، هـو أنه الآن إذا أراد استخدام تركيبك أن يقوم بحساب الدرجات بنفسـه وأن يقوم بتعيين حجم المواد بنفسه وأن يفعل ويفعل ... بالتالي ما هي الفائدة من التركيب الذي قمت بإنشاءه ، أيضاً التركيب الذي قمت بإنشاءه لن يفهـمه أحد ، فمثلاً المتغير في السطر الخامس وهـو itsNumber والذي تقصد به الرقم التسلسلي للطالب ، قد يفهـمه أحد المبرمجين على أنـه تاريخ أو الرقم الجامعي أو ربما أي شيء آخر والأمر ينطبق نفسـه على المتغيرات السابقـة......

هل فهـمت الآن ما هـو الفرق بين الواجهـة والمعالجـة... وأيضاً الفرق بين النظرة الكائنية للبرمجـة والبرمجـة الهيكلية ، وكيف تقوم البرمجـة الكائنية بتوفير الكثير عليك.

تذكر: عليك بالتركيز على الواجهات وليس المعالجـة

انتهى الدرس الثالث ، إذا لم تفهـم بعض الأجزاء من هذا الدرس بالرغـم من إعادة قراءتك له لأكثر من مرة فالسبب هـو أن بعض هذه المفاهيم لن تفهـمها إلا بالممارسة العـملية....

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

لمفضلة ,,,>>>اضافة للمفضلة >>> مواضيع مميزة >>>vector

الاجازة قربت ... ورح نتعلم منك : ) ....

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

شكراً لك أخي العـزيز الشمري

وأعتذر عـن عـدم إضافة الدرس الرابع والذي كان وقتـه أمس بسبب مشاكل في المنتدى ولكني سأضيفـه الآن

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

ملحق بالدرس الثالث:

لنفترض أنك أحد المبرمجين المستقلين ، وأن إدارة إحدى المدارس طلبت منك تصميم برنامج للدرجات لكي يستخدمه المعلمين فحسب ، هذا البرنامج يقوم بتحرير درجات الطلاب وجلب المعلومات الإحصائيـة لكل تقدير في كل مادة ، أي برنامج بسيط وليس نظام متكامل ؛ هـناك طريقتين للقيام بذلك وكلا الطريقتين تعتمد على كيفية تفكيرك ....

طريقة غير كائنية المنحـى:

في البداية يجب عليك أن تقوم بإنشاء الكود من الصفر ، يجب عليك الاهتمام بقضية المؤشرات والدوال وكل شيء ، فمثلاً ربما ستقوم بتعريف تركيب stuct للطالب الواحد وعـن طريق صفوف التأشير الذاتي سيكون لديك ما يمكن أن نطلق عليه قاعـدة بيانات للطلاب ، أيضاً ستقوم ربما بكتابة دالة للتعامل مع الملفات وأخرى لإيجاد المعلومات الإحصائيـة ، وهـناك الكثير الكثير من القضايا التي ستهتـم بها ...... من الممكن أن نلخص هذه الاهتمامات التي ستهتم بها في كلمـة واحدة هـي معالجـة البيانات أو المعالجـة .

طريقة كائنيـة المنحى:

حسناً أول ما عليك التفكير فيه ، هـو الكائنـات التي ستكون موجودة في برنامجك ، أول كائن هـو الطالب وثاني كائن هـو المادة ، وثالث كائن ربما يكون القائمة المرتبطة التي ستقوم بإنشاء ما يمكن أن نطلق عليه قاعـدة بيانات للطلاب ، المبرمج الذي يفكر بطريقة كائنية المنحـى ليس عليه التفكير في قضية المعالجـة فسيأتي وقتها لاحقاً ؛ الآن عليك أنت الذهاب إلى البرامج التي كتبتها سابقاً ، والبحث عـن كائنات البرنامج الذي ستقوم بكتابتـه وهي الطالب والمادة والقائمة المرتبطـة ، لنفترض أنك وجدت جميع الكائنات في برامج استخدمتها سابقاً ، يعتبر هذا الأمر جيداً للغاية ، الآن وبعـد أن وجدت الكائنات ماذا عليك أن تفعل؟ ؛ كمبرمج يفكر بطريقة كائنية عليك النظر الآن إلى واجهـة الكائن وليس معالجـة البيانات داخل الكائن ، بكلمات أخرى ، في كائن الطالب لن تنظر إلى كيفية حساب درجـة الطالب ، أو إلى قضية المؤشرات في كائن الطالب ، أو هل كائن الطالب صحيح أم خاطئ ،أنت لن تنظر إلى هذه القضايا ، لأنك أولاً تعتقد أن كائن الطالب أو كل كائن ستجـده هـو كائن مستقل وأنه مر بالعـديد من الاختبارات قبل أن يصل إلى يديك لذلك لن تنظر إلى مثل هذه القضايا ؛ الآن كما قلنا ستنظر إلى واجهـة كائن الطالب ، أو بشكل أدق الكائنات التي تندرج تحت التصنيف public ، لأنها هي الوجـه العام ، الآن وبعـد أن نظرت إلى جميع واجهـات كائنات البرنامج ، ماذا عليك أن تفعل ، كل ما عليك أن تفعله هـو الاهتمام بقضية التفاعل بين هذه الكائنات لينتج البرنامج الذي تريده.

قد يقول قائل؛ لنفترض أن المبرمج بحث في مكتبات البرامج السابقة التي قام ببرمجتها ولم يجد كائن الطالب مثلاً ، فماذا عليه أن يفعل ، الآن عليه أن يقوم بإنشاء كائن الطالب من الصفر ، ولكنه لن يكون مثل المبرمج الذي سيفكر بطريقة غير كائنية ، بل سيقوم أولاً بكتابة واجهـة الكائن ثم يهتـم بقضية المعالجـة ..... أي أن المبرمج الذي يعتمد الطريقة الكائنية سيفكر دائماً بالواجهات وليس معالجـة البيانات.

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

الدرس الرابع:

الكلمة المفتاحية class و public .

تعـدد أوجـه الدالات (التحـميل الزائد للدوال)

سنتعرف بداية على الكلمـة المفتاحية public في هذا الدرس وعلى الكلمـة class ، وعلى تقنية أخرى في الدوال تتميز بها السي بلس بلس عـن لغـة السي.

الكلمـة المفتاحيـة public (والتي تعـني عام) هي عـكس الكلمـة المفتاحية التي تعرفنا عليها في الدرس السابق وهي private (والتي تعـني خاص) المتغيرات والدوال الأعضاء التي تندرج تحت الكلمـة الدليلية public تقول لك بأن جميع أولئك الأعضاء هـم أعضاء عامـة وليسوا أعضاء خاصـة ، هذه الكلمة يتوقف عـملها عـندما تصل إلى الكلمـة الدليلية الأخرى private أو يتوقف التصريح عـن التركيب ...... أنظر إلى كيفية استخدام هذه الكلمـة المفتاحية :

1.	struct NameOfStruct
2. {
3. public:
4. int m;
5. int j;
6. private:
7. float k;
8. float I;
9. };

التركيب NameOfStruct يتألف من أربعـة أعضاء الاثنان الأولان هـما عضوان عامان أما الباقيان الأخيران فهـما عضوان خاصان ..... لا بد وهـنا أن تطرح سؤال وهـو هل هـناك فرق بين إذا وضعـنا كلمـة public أو تركنـاها ؛ حسناً في التراكيب فإن الوضع الافتراضي هـو أن جميع الأعضاء في التركيب هـم أعضاء عامـة وليسوا أعضاء خاصـة ، مالم توجـد كلمـة private حينها تصبح جميع الأعضاء المندرجـة تحتها أعضاء خاصـة ، لاحظ أن التركيب في المثال السابق هـو نفسه في هذا التركيب:

1.	struct NameOfStruct
2. {
3. int m;
4. int j;
5. private:
6. float k;
7. float I;
8. };

هذا هـو عـمل الكلمـة الدليلية public ، أتمنى منك أن تعرف عـملها حتى تتقن فائدتها فيما بعـد.

الكلمة الدليلية class :

الكلمـة class تعـني في اللغـة الإنجليزيـة صنف أو فصيل أو فئة وهي تقابل في لغـة السي بلس بلس الكلمـة struct ، في لغـة السي بلس بلس ليس هـناك أي فرق بين التراكيب والأصناف ، فكل ما ينطبق على الأصناف ينطبق على التراكيب ، ولا يوجد بين النوعين سوى فرق واحد فقط ، وهـو أن الوضع الافتراضي لأعضاء أي تركيب هـو الوضع العام أي public ، أما بالنسبة لأعضاء أي صنف فإن الوضع الافتراضي لحالتهـم هـو الوضع الخاص private ..... من الآن فصاعداً سأستغـني عـن الكلمـة الدليلية struct في هذه الدروس وأستبدلها بالكلمة الدليلة class ، ليس هـناك أي ميزة حتى أختار أحدهـما سوى أن الأمر ارتاح إليه ، كما أن الكلمة الدليلية struct تذكرني بلغـة السي حينما أكون أعـمل على لغـة السي بلس بلس ...

هـناك نصيحـة برمجيـة هامـة أخرى أود ذكرها ولو أن ليست من ضمن السياق ، كل ما هـو ليس ضرورياً أن يكون عضواً عاماً (حتى وإن كان دالة ) وأنا أعـني بليس ضرورياً أي ليس من ضمن الواجهـة فيجب أن تجعله عضواً خاصاً.

سنترك الآن الأصناف والتراكيب جانباً في بقية هذا الدرس وسنرجع إليها في الدرس القادم ؛ بقية هذا الدرس سنخصصها لميزة تتميز بها السي بلس بلس عـن السي في موضوع الدوال وهـو تعـدد أوجـه الدالات أو التحـميل الزائد للدوال.

التحـميل الزائد للدوال:ا

ستعرت هذه الفقرة بكاملها من كتابي الإكسير لأني لم أستطع أن أكتب شرحاً أفضل من شرحي السابق.

يعتبر هذا الموضوع هـو أول نـوع من أنـواع تعدد الاوجـه والتي هي ثلاثة أنـواع وتعدد الأوجـه أحد أساسيات البرمجة الكائنية ، وهذا يعـني أنـه لن يمكنك تطبيق هذا الموضوع على لغـة السي (إن وجد مترجمات للغة السي مستقلة عـن مترجمات السي بلس بلس).

كما قلت أن من أحد أهـم أهداف البرمجة الكائنية هـو الوصول إلى استقلالية الكود الذي تكتبه وإمكانية إعادة استخدامـه وسهولة فعل ذلك ، والتحـميل الزائد يعـد أحد الأساليب القوية لفعل ذلك.

التحـميل الزائد للتوابع يعـني وجود نسخ أخرى تحمل نفس اسم التابع الزائد التحميل ولكنها تختلف إما في عدد الوسائط أو نـوع الوسائط أو حتى ترتيب هذه الوسائط.

والفائدة من ذلك تظهر فيما لو فهـمت موضوع الوسائط الافتراضية ، فوجود الوسائط الافتراضية في التوابع يمكنك من استدعاء الدالة بطريقتين مختلفتين إحداها بدون ذكر قيم الوسائط الافتراضية والأخرى بتغيير قيم الوسائط الافتراضية ، لنفرض أنك قررت كتابة أحد التوابع وهـو التابع Find ، وتريد من هذا التابع أن يقوم بالبحث في أي مصفوفة يطلبها المستخدم مع العلم أن هـناك مشكلة كبيرة وهي كيفية جعل هذا التابع يتعامل مع جميع أنواع المصفوفات int و char و float ... وغيرها الحل الوحيد هـو أن تقوم بزيادة تحـميل التابع find ، أي ستصبح النماذج المصغرة لنسخ التابع find، هكذا:

	int find (int [] , int );
char find (char [] , char);
float find (float [] , float );

وحينما تصل لمرحلة تعريف هذه التوابع ، فيجب عليك تعريف كل نموذج على حدة ولن يكفيك تعريف تابع واحد فحسب.

عليك أن تعلم أن التحميل الزائد لأي تابع يعـني أن هـناك إصدارات أو نسخ أو توابع أخرى تحمل نفس اسم هذا التابع ولكنها تختلف في الوسائط سواء في العدد أو النوع.

سنقوم الآن بتقليد التابع Abs الذي يعيد القيمة المطلقة لأي عدد تدخله من المكتبة stdio في لغـة C ، ولربما تقوم أنت بتطويره حتى يصبح أفضل من التابع الموجود في لغـة C :

1.	#include <iostream>
2. using namespace std;
3.
4. int Abs (int );
5. float Abs(float );
6. double Abs (double );
7.
8. int main()
9. {
10.  int Int=0;
11.  float Float=0;
12.  double Double=0;
13.  
14.  cout << "Int:\t"; cin >> Int;
15.  cout << "Float:\t"; cin >> Float;
16.  cout << "Double:\t";cin >> Double;
17.  cout << endl << endl;
18.
19.  cout << "Int:\t" << Abs(Int) << endl;
20.  cout << "Float:\t" << Abs (Float) << endl;
21.  cout << "Double:\t" << Abs(Double) << endl;
22.  cout << endl;
23.
24.  return 0;
25. }
26. int Abs(int X)
27. {
28.  return X<0 ? -X : X;
29. }
30.
31. float Abs(float X)
32. {
33.  return X<0 ? -X : X;
34. }
35.
36. double Abs (double X)
37. {
38.  return X<0 ? -X :X;
39. }

• انظر إلى النماذج المصغرة للتوابع Abs( ) ، جميعها تأحذ أنـواعاً مختلفة وسيقوم المترجم حينما تقوم باستدعاء هذه التوابع بالبحث عـن التابع المناسب ، النماذج موجودة في الأسطر 3 و 5 و 6.

• في الأسطر 10 و 11 و 13 تم الإعلان عن ثلاث متغيرات من الأنواع int و float و double وتسمية كل متغير بنفس مسمى نـوعه ولكن بجعل الحرف الأول كبيراً والسبب في هذا الإجراء حتى تستطيع التفريق بينها في البرنامج

• تطلب الأسطر 14 و 15 و 16 منك إدخال قيم هذه المتغيرات ، حتى تستطيع فيما بعـد إيجاد القيمة المطلقة لكل عـدد.

• السطر 19 يقوم بطباعة القيمة المطلقة للمتغير من النـوع int ، وكما ترى فهـو يقوم بطباعة القيمة العائدة للتابع int Abs( ) ، وكما ترى فإن التنفيذ سينتقل إلى البحث عـن التابع المناسب لمثل هذا النوع من الوسائط والتابع الأفضل هـو في السطر 26 .

• في السطر 28 ، يقوم البرنامج بمقارنة العـدد الممرر (الذي نود إيجاد القيمة المطلقة له) مع الصفر وفي حال كان أصغر فإننا نعيد العدد ولكن بقيمة سالبة وبالتالي فعـندما تدخل العـدد -2 فإن المقارنة ستنجح وبالتالي سيقوم التابع بإرجاع القيمة بعـد إضافة السالب إليها أي ستصبح القيمة العائدة هـكذا - - 2 ، والتي رياضياً تساوي 2 ، أما في حال لم تنجح المقارنة أي أن العدد أكبر من الصفر أو مساوي له فسيعيد التابع نفس القيمة ويقوم التابع main( ) بطباعتها في السطر 19 .

• نفس الأمر سيحدث في السطرين 20 و 21 .

بالرغـم من سهولة هذا الموضوع إلا أنه يعتبر أحد أهـم الإمكانات في لغة السي بلس بلس وفي البرمجة الكائنية بشكل عام ، وخاصة حينما تبدأ في التعامل مع الكائنـات.

محاذير عـند التحـميل الزائد للتوابع:

هـناك بعض الأخطاء عـندما تقوم بالتحميل الزائد للتوابع ، والتي يغفل عـنها الكثيرون ، وهذه هـي أهـمها:

1- لن يكون بإمكانك زيادة تحـميل أي تابع اعتماداً على القيمة العائدة فقط ، تعتبر هذه الإعلانات عـن التوابع خاطئـة:

	int Abs(int , int );
float Abs( int , int );

والسبب بسيط وهـو أن المترجم لن يعلم أبداً ما هـو التابع الذي سيقوم باستدعاءه بالضبط ، لأن الوسائط هـي نفسها.

2- لن يكون بإمكانك زيادة تحـميل أي تابع في حال كانت له نفس قائمة الوسائط حتى وإن كانت بعض وسائطة افتراضية ، أنظر إلى هذا المثال:

	int function(int a ,int b);
int function(int a,int b ,int c=100);

والسبب أنه حين استدعاء هذا التابع بواسطـة وسيطين وليس ثلاثة فحينها لن يعرف المترجم أي تابع يستدعي.

3-أيضاً لن يكون بإمكانك زيادة تحـميل تابع على هذا الشكل:

int function(int a);
int function(const int a);

تذكر لكي ينجح التحـميل الزائد للتوابع ، فعلى التوابع التي تحمل نفس اسم التابع أن تختلف في قائمة الوسائط سواء في العدد أو الترتيب أو النوع أو أي شيء آخر مع الأخذ بعين الاعتبار المحاذير السابقة.

قد تقول الآن بعـد انتهاء الدرس ما الذي استفدنـاه منـه ، الجواب هـو أنـه سيقوم بتزويدك بطرق وتقنيات جديدة لتطوير كائناتك

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

مشكور يافكتور

نرجو التثبيت .............

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

الدرس الخامس

دوال أكثر تقدماً...

زيادة تحـميل دالة البناء.....

دالة بناء النسخـة

دعـنا الآن نطبق الدرس السابق (التحـميل الزائد للدوال ) على الكائنـات ، هل بإمكاننا مثلاً أن نزيد تحـميل دالة البناء وأيضاً دالة الهـدم..

كما قلنا في الدروس السابقـة ، إن من إحدى خصائص دالة البناء ، هي قدرتها على استقبال أي عـدد من الوسائط ، إذاً فبإمكاننا أن نزيد تحـميل هذه الدالة ، دعـنا الآن نفكر بشأن زيادة تحـميل دالة الهـدم .. هل بإمكاننا زيادة تحـميلها ، ألم تفهـم من الدروس السابقة أن هذه الدالة ، لا تستقبل أي وسائط أبداً ، بالتالي فإنه لا يمكن زيادة تحـميلها.....

ما الذي سنستفيده من زيادة تحـميل دالة البناء ، الذي سنسفيده هـو التماسك ، أقصد تماسك الكائن الذي تقوم أنت بكتابتـه.....

يوجد في عالم البرمجـة الكائنيـة نوعان اثنان من المبرمجيـن ، الأول: هـو صانع الأصناف ، والثاني هـو مستخدم الأصناف ؛ النـوع الأول مهـمته الأساسية هي أن يقوم بصنع صنف متماسك للغاية وقابل للاستخدام بأية طريقـة ونحن في هذه الحالة من هذا النـوع ؛ والهـدف الأساسي هي أن نقوم بتسهيل مهـمـة مستخدم الصنف (أقصد الصنف الذي نقوم بكتابته) ، ماهي الطريقة التي بإمكاننا فعلها لتسهيل مهـمـة مستخدم الصنف ، هي أن نقوم بصنع واجهـة للصنف قوية ومتماسكـة لأقصى قدرة برمجية نملكها ، من ضمن القوة التي ستحسب لواجهـة الصنف الذي تقوم بكتابته هي أن تكون جميع الدوال جاهـزة للاستعـمال بأي عـدد ممكن من الوسائط وحتى بأي نـوع محدد من الوسائط....

من ضمن الدوال الأساسيـة هي دالة البناء ، على دالة البناء أن تكون قادرة على العـمل في أي ظرف ممكن ..... أنظر إلى صنف الطالب الذي قمنا بتطويره على مدى الدروس الأربعـة السابقـة:

1.	class student {
2. public:
3.       student(int);
4.       ~student();
5.       int GetitsNumber();
6.       int GetNumberOfCourses();
7.        float GetitsAvg();
8.        float GetgradesOfCourses(int );
9.        void SetitsNumber(int );
10.  void SetNumberOfCourses(int);
11.  void SetItsAvg(float );
12.  void SetgradesOfCourses(int , float);
13.  void CalculatorOfAvg(int = 100);
14. private:
15.  float* gradesOfCourses;
16.  float itsAvg;
17.  int NumberOfCourses;
18.  int itsNumber;
19.  };

إذا أتى أحد المبرمجين (من الذين يستخدمون الأصناف ) وقام بكتابة السطر الآتي:

1.	student a;

فإن المترجم لن يقوم بترجمـة ذلك السطر ، والسبب في ذلك هـو أن الصنف الذي قمت بكتابتـه يجب أن تستقبل دالة بناءه بارامتر واحد ، سيتذمر مستخدم الصنف من هذا الشيء وسيقوم بإجراء تعـديلات على صنف student ، مما يعـني الآن أنك قد قمت بانتهاك أحد أهـداف البرمجـة الكائنية ، وهـو زيادة الإنتاجيـة ، وقد يتوقف بناء النظام الذي يقوم بعـمله الفريق البرمجي حتى يتم تعـديل الصنف الذي قمت بكتابته ، حتى تستطيع أن تحل هذه المشكلـة عليك بزيادة تحـميل دالة البناء ، وحتى يكون السطر السابق صحيحاً أيضاً...

قم بإضافة دالة البناء الجـديدة (الزائدة التحميل) ضمن التصريح عـن الصنف ... وهذا هـو تعريف هذه الدالة الجـديدة:

1.	student::student()
2. {
3. gradesOfCourses= 0;
4. NumberOfCourses= 0;
5. itsNumber=0;
6. }

تقوم هذه الدالة بتصفير أغلب المتغيرات الأعضاء ضمن تصريح الصنف student ، إلا أنه ستظهر هـنا مشاكل خطيرة وجمـة في هذا الصنف student ... والسبب في ذلك هـو ضعف التصميم لهذا الصنف ... لا أقصد هـنا أن المبادئ التي قضيت الدروس السابقة وأنا أؤكد عليها خاطئـة أو أنها غير ناجعـة .. ولكن السبب هـو أني قمت بانتهاك بعضها وأنا أقوم بتطوير هذا الصنف لأغراض تعليميـة ليس إلا ... ولأجل ذلك ، فسأوقف تطوير هذا الصنف student في هذه الدروس (بعـد درس أو درسين) ، وسأقوم أيضاً بترك مشروع لك لبناء صنف student آخر ...

الأسباب الخطيرة التي أدت لضعف تصميم هذا الصنف هـو أن مستخدم الصنف إذا قام بكتابة هذا السطر:

1.	student a;

فإنه سيقوم بتصفير المؤشر gradesOfCourses ، وبالتالي فلن يعـود بإمكانه إضافة مواد جـديدة حتى يتم احتسابها .... وهـناك أخطاء تصميمية كثيرة في هذا الصنف..

سيستمر هذا الصنف معـنا في هذا الدرس وربما الدرس القادم ... وربما أقوم بتعـديله حتى يستمر معـنا طيلة هذه الدروس..

كما قلنا لن يكون بإمكانك زيادة تحـميل دالة الهـدم بسبب أنها أصلاً لا تستقبل أي وسائط .......

لقد تعلمت حتى الآن دالتين مهـمتين هـما: دالة البناء ودالة الهـدم ..... في حال لم تقـم بكتابة هاتين الدالتين عـندما تقوم بإنشاء صنف فإن المترجم سيقوم بتزويدك افتراضياً بهاتين الدالتين ، هـناك دالة أخرى مهـمـة ، وهي تعتبر دالة بناء وفي حال لم تقم بتعريفها سيقوم المترجم بتزويدك بها ، وهي دالة بناء النسخـة.

دالة بناء النسخـة:

هذه الدالة هي دالة عاديـة للغـاية ولا فرق بينها وبين دوال البناء الأخرى ، ولكن المميز فيها هـي أنها تقوم ببناء نسخـة عـن نفسها ، لنرجع إلى الصنف student ، الذي قمنا ببناءه على مدى الدروس الأربعـة السابقـة ، إذا أراد مستخدم الصنف ، استخدام الأمر التالي:

1.	student a(10);
2. a.CalculatorOfAvg( 4 );
3. student b=a;

الذي يعـنيني الآن هـو الأمر الثالث بالتحـديد ، والذي سينتج عـنه نسخ محتويات الكائن a إلى محتويات الكائن b ، لن يعترض المترجم على هذا الأمر وذلك لأنـه يزودك بالفعل دالة عضو (غير دالة البناء والهـدم) تقوم بعـمل المساواة ، ولكن دعـنا الآن نتحدث قليلاً عـن المشاكل التي ستظهر إذا قمت بتنفيذها في مترجمـك ...

لم أجرب هذا المثال في Visual C++ 6 وإنما جربتـه في Visual C++.Net ، وسبب ذكري للمترجمات التي أستخدمها حتى تفهـم أن بعض النتائج التي ستظهر لديك ستكون مخالفـة لما قد يظهر لدي والسبب اختلاف المترجمات ، نرجع إلى موضوعـنا إذا قمت بتنفيذ الأمر السابق وبالتحـديد في السطر الثالث ، فإن المترجم لن يعترض أبداً على ما تقوم بـه ولكن حينما يتجاوز السطر الثالث بأسطر قليلـة ينهار انهياراً تاماً ، وفي حال لم يكـن هـناك أي أسطر بعـد السطر الثالث فسينهار عـند نهاية البرنامج ، السبب في ذلك هـو الذاكرة وبالتحـديد في المؤشر gradesOfCourses ... قبل أن تقرأ الفقرة القادمـة حاول أن تخمن السبب وراء انهيار البرنامج ودور المؤشر gradesOfCourses في عـمل ذلك .........

من الأفضل أن تخمن السبب حتى تثبت لنفسك أنك تريد التعلم بالفعل وليس التلقي لكتابة أمثلـة تتفاخر بها أمام زملائك وأقرانك ؛ سنتحدث الآن عـن السطر الثالث ، والذي هـو بالشكل التالي:

student b = a;

دعـنا نفكر قليلاً في ما تعـنيـه هذه العلامـة (علامـة الإسناد = ) ، أنك تقول فيها للمترجـم يا مترجم قم بأخذ جميع محتويات المتغيرات الأعضاء في الكائن a وضعها في المتغيرات الأعضاء في الكائن b ، وهذا ما يقوم به المترجم لن يكون هـناك أية مشاكل حينما تكون المتغيرات الأعضاء عبارة عـن متغيرات عاديـة تحـمل قيـم ، ولكن ماذا لو كانت هذه المتغيرات عبارة عـن مؤشرات تحـمل عـناوين في الذاكرة وليس قيـم ، سينتهي الأمر بأن المؤشر gradesOfCourses في الكائن a سيشير إلى نفس مكان الذاكرة الذي يشير إليه المؤشر gradesOfCourses في الكائن b ، أرجع إلى تعريفات الدوال الأعضاء وأنظر إلى تعريف دالة الهـدم سيتم إلغاء الذاكرة للمؤشر gradesOfCourses في حال تم هـدم البرنامج ، إن ذلك يعـني الآن أن أي كائن سيتم هـدمـه من بين الاثنين سيهـدم معـه الآخر ، وذلك يعـني أن أي تغيير في قيم المصفوفـة أو المؤشر gradesOfCourses في أحد الكائنين سينتج عـنه تغير القيم تلقائياً في الكائن الآخر ... السؤال كيف ستحل هذه المشكلـة ........

الجواب هـو القيام بكتابة دالة بناء النسخـة التي ستحل هذه المشكلـة نهائياً والتي أصلاً يزودك المترجم بها في حال لم تقـم بكتابة واحدة ........... أنظر إلى الإعلان عـن دالة بناء النسخـة:

student (const student& );

لاحـظ أن دالة بناء النسخـة لها نفس اسم الصنف مما يعـني أنها دالة بناء في الأساس ، أنظر أيضاً إلى الوسائط التي تحملها ، إنها تحـمل مرجعية من النـوع student ،وهي ثابتـة const ، لا تنسى أن هذا هـو الشكل الأساسي لدالة بناء النسخـة ...... أنظر الآن إلى تعريف دالة بناء النسخـة ، وأنظر كيف سنقوم بحجز الذاكرة للمؤشر gradesOfCourses بشكل آمن لا تشوبه أي شائبـة ، أنظر وحاول أن تفهـم الكـود قبل قراءة باقي الدرس:

student::student(const student& rhs)
{
NumberOfCourses=rhs.GetNumberOfCourses();
gradesOfCourses=new float[NumberOfCourses];
itsNumber=rhs.GetitsNumber();
itsAvg=rhs.GetitsAvg();
int i=0;
for(i=0;i<NumberOfCourses;i++)
 gradesOfCourses[i]=rhs.GetgradesOfCourses(i);
}

لن أشرح تعريف هذه الدالة ، لأني أعتقد أنك تملك ما يكفي من معرفـة حتى تعلم عـن أي شيء أتحدث ..........

هـناك ملاحظات يجب التنويـه إليها لأنها مهـمـة للغاية ...

ملاحـظة:

لا تنسى أبداً أن تضع في جميع محددات الوصول Get الكلمـة const ، إذا لم تفعل ذلك فلن يعـمل دالة بناء النسخـة....

ملاحظـة:

البعض سيقوم بتجريب أمثلة وقد تعـمل لديه بسبب قدم المترجم الذي يملكـه (وحتى المترجمات الجـديدة تقبل هذه الأخطاء) ، مثل هذا الإعلان عـن دالة بناء النسخـة:

student (const student rhs);

هذا السطر لن يعـمل في أي مترجم سواء المترجمات القديمـة أو الجـديدة إلا إن كان المترجم الذي تستخدمـه للغـة أخرى غير لغـة السي بلس بلس......

انتهى الدرس الخامس ..........

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

إخـوتي الأعـزاء ... لا أدري ولكني أحس أني أكتب وأضع هذه الدروس لنفسي

أين تفاعلكم

هل تريدون مني الاستمرار

كما أني وضعت سؤال لم يجب عليه أحد لماذا؟؟؟

هل أكمل أم ماذا؟؟

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

أكمل فبعض الاعضاء يتابعون مواضوعك

أنا منهم

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

بالنسبة للخطأ في الكود الذي كتبته

.. انا لست متاكدة لكن هل هو ان الكونستركتور في جوى public والمفروض يكون بره

لان public مستقل بذاته

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

بالعكس اخي دروسك مفيدة جدا

فانا صحيح اخذت كورس سي بلس بلس لكن اريد تطوير نفسي

وطريقة تفكيري

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
إخـوتي الأعـزاء ... لا أدري ولكني أحس أني أكتب وأضع هذه الدروس لنفسي

هههه .. اعرف شعورك .... :(

هل أكمل أم ماذا؟؟

كمل .. مع اني اعتقد انك لو كملت بدون تفاعل ستأتي نقطة فيما بعد تصاب فيها بالاحباط و تقرر فيها التوقف التام ..

لكن كمل .. و الله كريم.

اذا تريد حط شوية تمارين تطلب من الاعضاء حلها .. حتى تشوف مستوى المتابعة, او تجبر الاعضاء على المتابعة.

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
زوار
This topic is now closed to further replies.

  • يستعرض القسم حالياً   0 members

    لا يوجد أعضاء مسجلين يشاهدون هذه الصفحة .