الخميس، 26 مارس 2015

المعـامل (::) :

المعـامل (::) :هـناك معـامل آخر لم نتعرض له وهـو معـامل الوصول إلى المتغيرات العامـة
وهـو :: ، انظر إلى هذا المثال:
int a=10;
void function( )
{ int a= 5 }
كما تلاحـظ فـإن هــناك متغيـر خـاص أو محلـي لـه اسـم a للتـابع function ،
وهــناك أيضـاً متغيـر عـام ، السـي بلـس بلـس تسـمح لـك بفعـل ذلـك ولكـن
المتغيــر العــام ســيتم إســتبعاده أو إخفــاءه وســتكون الأولويـــة فــي التــابع
function للمتغيــرات المحليــة ولــيس للمتغيــرات العامـــة ، وحتــى تســتطيع
الوصول إلى المتغير العام ضمن كتلة التابع function فعليـك أن تقـوم بكتابـة
المعامل :: حتى تصل إليه أنظر لهذا الأمر الذي نفترض أنـه ضمن كتلـة التـابع
: function
cout << ::a ;
لن يقـوم هـذا الأمـر بطباعــة القيمــة الخاصـة بـالمتغير الخـاص بـل بالقيمــة
الخاصـة بالمتغير العام لأننا قمنا بكتابة المعامل :: قبل اسم المتغير.
الوسائط الإفتراضيـة:
أحــد أهــم أهــداف أي برمجــة هــو إعـادة الاسـتخدام ، أي إعـادة اسـتخدام
الاكواد السابقـة وحتى نصل إلى هذا الهـدف فلا بد علينا من جعـل اسـتخدام
هذه الأكواد السابقة بسيطاً للغايـة وبـدون أي تعقيـد ، انظـر مـثلاً للكـائن cin
وكيف أن إستخدامه بسـيط وميسـر وأيضـاً للدالـة ( )printf فـي لغـة السـي
ومدى سهولتها وهذا أيضاً ما نحـاول الوصول إليه من خلال هذا الكتاب.
بإمكاننا تسهيل استخدام أي دالة بواسطـة الوسائط الافتراضيـة (البارامترات
الافتراضية) وهذه الأداة تمكننا من تسـهيل الكــود لدرجـة كبيـرة ، هـل تتـذكر
التابع ( )getline ، هذا التابع يحتـوي علـى ثـلاث بـارمترات ، ولكنـك تسـتطيع
التعامل معـه على أنه يستقبل بارامترين اثنـين وتسـتطيع إذا أردت اسـتخدام
ثلاث بارامترات ، نفس الأمر ينطبق هـنا ، بإمكاننا إنشاء توابـع بتلـك الطريقــة
ووسيلتنا لذلك هـي الوسائط الافتراضية.
سـنقوم الآن بكتابـة مثـال كــودي وهـذه المـرة سـيقوم هـذا المثـال بحسـاب
النسـبة المئويــة ، حيـث أنــه سـيقوم بحسـاب النسـبة مـن 100 افتراضــياً ،
وبإمكان المستخدم حساب النسبة من 100 أو أي رقم آخر يريده.
1. float rate(float a,float b ,float c=100)
2. {
3. float j=0;
4. j= (a*c)/b;
5. return j;
6. }
انظر إلى السطر الأول تجـد أن البارامتر الثالث غريب بعض الشيء حيث قمنا
باسناد البارامتر إلـى القيمــة 100 ، وبـذلك سـيكون بإمكانـك اسـتخدام هـذه
القيمـة افتراضياً ، بإمكانك استدعاء هذا التابع بهذا الشكل:
rate ( 50 , 100)
أو بهذا الشكل إن أردت:
rate ( 20, 100 , 1000)
والفـرق بـين الاسـتدعائين أن البـارامتر الثالـث للتـابع المسـتدعى الأول هــو
سيكون افتراضياً بقيمـة 100 ، أمـا التـابع الثالـث فلقـد أراد المسـتخدم تغييـر
هذه القيمـة وبالتالي فلقد قام البرنـامج باسـتبعاد القيمـة الافتراضـية ووضـع
القيمة التي قام المستخدم بوضعها.
سنرى الآن كيف سيكون استخدامنا لهذا التابع فـي وسـط برنـامج حقيقـي ،
عليـك أن تعلـم أن القيمــة الافتراضــية لا تكتـب أبـداً فـي رأس التـابع إلا فـي
النموذج المصغر فقط ، أما تعريف التابع فلا تقم بكتابة القيمـة الافتراضـية وإلا
فـإن المتـرجم سيصـدر خــطأ ، انظــر لهـذا المثـال ، وكيـف تـم تطبيـق الكـلام
الحالي:
CODE
1. #include <iostream>
2. using namespace std;
3.
4.
5. float rate (float a,float b,float c=100);
6.
7. void main()
8. {
9. float i,j,k,avg;
10. cout << "Please Enter the number?\n";
11. cin >> i;
12. cout << "from:\t";
13. cin >> j;
14. cout << "the Avrege:";
15. cin >> avg;
16.
17. k=rate (i ,j,avg);
18. cout << endl << k << endl;
19.
20. }
21.
22. float rate(float a,float b ,float c)
23. {
24. float j=0;
25. j= (a*c)/b;
26. return j;
27. }
قارن بين رأس التابع في السطر 22 والنموذج المصـغر للتـابع فـي السـطر 5
تستنتج أن النمـوذج المصـغر بإمكانـه الاحتـواء علـى قـيم افتراضـية أمـا رأس
التابع أو تعريف التابع فليس بإمكانـه الاحتـواء على أي قيمـة افتراضية.
إعادة أكثر من قيمـة بواسطـة المؤشرات أو المرجعيات:
الآن سنأتي إلى التطبيق الفعلي للمؤشرات ؛ هل تتـذكر التوابـع ألـيس فـي
نهايـة كل تابع مالم يكـن void العبارة التاليـة: return (Value);
حيث value القيمة المعادة.
كما ترى فإن جميع الدوال أو الإجراءات لا تعـود إلا بقيمـة واحـدة ولا تسـتطيع
العـودة بأكثر من قيـمـة ، الآن سنفكر بطريقـة تمكننا من جعـل التوابـع تعــود
بأكثر من قيمـة.
ما رأيك الآن بدلاً من أن نمرر للتوابع القـيم أن نمـرر لهـا عــناوين تلـك القيــم ؛
سنكتب برنامج هذا البرنامج يحــوي تابعـان التـابع main وتـابع آخـر سـنطلق
عليه plus سيعــيد هـذا الإجـراء قيمتـين وسـيقوم الإجـراء main بطباعتهــما
وليس التابع plus .
1 #include < iostream.h>
2 void plus (int num1,int num2,int *plus1,int *plus2)
3 {
4 *plus1=num1 + num2;
5 *plus2=num1*num2;
6 }
78
void mian ( )
9 {
10 int num1,num2,plus1,plus2;
11 plus (num1,num2, &plus1 , & plus2);
12 cout << plus1 << endl;
13 cout << plus2 << endl;
14 }
الآن وكما ترى فإن قيم plus1 و plus2 ستؤدي المطلـوب منهـا حيـث plus1
يجمع عـددان و plus2 يضـرب عـددان بالرغــم مـن أن المعالجــة لا تتــم فـي
التابع ()main بل فـي التـابع plus وكمـا تلاحـظ فـإن التـابع plus لا يعــود أي
قيمـة لأنه void ؛ كما تلاحظ أعـلنا عـن عددان مهيئان مسبقاً وعددان لم يهيئا
في السطر العاشر ؛ بعـد ذلـك قمنـا بتمريـر قيمــة العــددان num1 و num2
إلى الإجراء plus أما بالنسبة للعــددان الآخـران فلـم نمـرر قيمهــما بـل مررنـا
عـناوين تلك القيـم كما هـو واضح من السطر الحادي عشر ؛ كما درسـنا فـي
هذا الموضوع (موضوع التوابع) أنهـا تنشأ نسخ مـن المتغيـرات الممـررة إليهـا
أما في هذه الحالة فهي لم تقوم بإنشاء نسخــة بـل أخـذت النسـخ الأصليــة
من تلـك المتغيـرات وهــي عــناوينها ... الآن يتفـرع البرنـامج إلـى التـابع plus
والذي عرفناه في السطر الثاني وكما تلاحظ فهــو يحتــوي عـددان مـن نــوع
int ومتغيران آخران لكن مؤشرات هـذه المـرة وليسـا متغيـرات عاديــة .. هـل
تعرف لماذا .. كما تلاحـظ فلقـد مررنـا عــناوين تلـك المتغيـرات ؛ البرنـامج الآن
بحـاجـة إلى متغير ليحمل تلـك لعــناوين وكنـا تعلـم فـإن المؤشـر هــو متغيـر
يحمل عـنوان .. ثم في السطر الرابع والخامس تمت معالجـة القيم حيث في
السطر الأول جمعـنا العددان وفي السطر الخـامس ضـربنا العـددان ثـم فـي
السطر السادس عــدنا مـرة أخــرى إلـى الإجـراء ()main ثـم فـي السـطران
الثاني عشر والثالث عشر قمنا بطباعـة النتائج .... وهـكذا انتهـى البرنامج.
خلاصـة هذا الشرح ؛ أنـه لكي تجعل التابع يعـود بأكثر من قيمـة عليك أولاً أن
تمرر عـناوين أو مرجعيـات تلـك القـيم ولـيس القـيم بحـد ذاتهـا ؛ حينمـا تقـوم
بتعريــف التــابع فإنــك تضــع فــي قائمـــة الوســائط مؤشــرات لتلــك العـــناوين
المرسلة حتى تستطيع حـملها
كما تلاحظ فلقد استخـدمنا في المثال السابق المؤشرات ... ما رأيـك الآن أن
نستخـدم بـدلاً عــن المؤشـرات المرجعيـات... انظـر لهـذا المثـال وهــو نفـس
المثال السابق لكن هذه المرة نستخـدم المرجعيات بدلاً من المؤشرات:
1 #include < iostream.h>
2 void plus (int num1,int num2,int &plus1,int &plus2)
3 {
4 plus1=num1 + num2;
5 plus2=num1*num2;
6 }
78
void mian ( )
9 {
10 int num1,num2,plus1,plus2;
11 plus (num1,num2, plus1 , plus2);
12 cout << plus1 << endl;
13 cout << plus2 << endl;
14 }
المثال نفس مثال المؤشرات عـدا في السطر الحادي عشر فلقـد تـم إرسـال
القيم بدون أي تغيير لها أما تعريف التابع plus في السطر الثاني فلقـد جعلنـا
تلك القيم إشارات .
بالرغـــم مـن أن المثـالين السـابقين سيعــملان بـنفس الجــودة إلا أن المثـال
الأخير بإستخدام المرجعيات أقوى مـن المثـال السـابق فهــو لا يجعلـك تفكـر
عـند إرسال القيم للإجـراء ؛ فـلا يجعلـك تقـول هـل أرسـل عــنوان القيمــة أم
القيمـة ؛ وهذا مـا تحــاول ++C الوصـول إليـه ؛ خاصــة فـي أمــور البرمجــة
الكائنيـة .. عـموماً سنصل إلى جميع نقاط هذه الفوائـد فـي وقـت لاحـق مـن
الكتاب

ليست هناك تعليقات:

إرسال تعليق