مؤشرات لكائنات في ++C
مؤشرات لكائنات
يمكن أن يشير مؤشر لكائن كما يشير لأي نوع أخر من البيانات . فلو تصورنا أننا لا نعرف مسبقا عد الكائنات المطلوبة , يمكننا أن نستخدم المؤثر new ليخصص المساحة التي يتضح أنها مطلوبة أثناء تشغيل البرنامج , وقد رأينا أن المؤثر new يعيد مؤشرا لكائن غير معروف الاسم , وسوف نري في المثال التالي أسلوبين لإنشاء الكائنات , الأول هو الأسلوب والثاني باستخدام المؤثر المذكور .
englptr.cpp
// englptr.cpp
// accessing member functions by pointer
#include <iostream.h>
#include <conio.h>
class Distance // English Distance class
{
private:
int feet;
float inches;
public:
void getdist() // get length from user
{
cout << "\nEnter feet: "; cin >> feet;
cout << "Enter inches: "; cin >> inches;
}
void showdist() // display distance
{ cout << feet << "\'-" << inches << '\"'; }
};
void main()
{
Distance dist; // define a named Distance object
dist.getdist(); // access object members
dist.showdist(); // with dot operator
Distance* distptr; // pointer to Distance
distptr = new Distance; // points to new Distance object
distptr->getdist(); // access object members
distptr->showdist(); // with -> operator
getche();
}
أنشأنا في هذا البرنامج كائنا dist ينتمي للفئة distance بالأسلوب المألوف لنا ثم أنشأنا كائنا باستخدام المؤثر new والذي يعيد مؤشرا هو distptr .
لاستثارة الدوال المنتمية للكائن الذي يشير له هذا المؤثر لن يكون معامل النقطة مجديا فهذا المعامل يتطلب اسم الكائن إلي يساره واسم الكائن غير معروف لنا بمعني أن الصيغة التالي ليست مقبولة :
Distptr.getdist();
ببساطة لأن المذكور إلي يسار معامل النقطة هو مؤشر للكائن وليس الكائن نفسه .
الحل المباشر أن نضع إلي يسار معامل النقطة ما يشير إليه المؤشر , وقد تعلمنا القيام بذلك فهو الصيغة *distptr فتكون الصيغة التالية مقبولة تماما :
(*distptr).getdist ();
علي أن لغة السي ++ أمدتنا بمؤثر أكثر رشاقة هو المؤثر السهمي أو الانتماء membership-access operator , وهو علي الصورة التالية " >- " كما هو مبين بالمثال ومنه تري أن هذا المؤثر يلعب مع مؤشرات الكائنات دور النقطة مع الكائنات ذاتها .
أسلوب أخر للمؤثر new
نعرض عليك صيغة أخري لاستخدام المؤثر new في المثال التالي .
englref.cpp
// englref.cpp
// defererencing pointer returned by new
#include <iostream.h>
#include <conio.h>
class Distance // English Distance class
{
private:
int feet;
float inches;
public:
void getdist() // get length from user
{
cout << "\nEnter feet: "; cin >> feet;
cout << "Enter inches: "; cin >> inches;
}
void showdist() // display distance
{ cout << feet << "\'-" << inches << '\"'; }
};
void main()
{
Distance& dist = *(new Distance); // create Distance object
// alias is "dist"
dist.getdist(); // access object members
dist.showdist(); // with dot operator
getche();
}
وفي هذا البرنامج عرفنا الكائن باسمه كالمعتاد عدا إلحاق المؤثر & باسم الفئة , وساوينا العبارة بالعبارة : *(new distance) , وتمكننا هذه الصيغة من التعامل باسم الكائن ومؤشر النقطة كالأسلوب المألوف لنا . وهذه الصيغة أقل انتشارا من الأسلوبين المبينين في البرنامج السابق ] لأن معرفة اسم الكائن ليس بذي أهمية في كثير من التطبيقات , وستري في كثير من الأمثلة أن التعامل مع مؤشرات البيانات أكثر مرونة من التعامل مع البيانات نفسها [ .
مصفوفة مؤشرات لكائنات
من التصميمات المألوفة في البرمجة مصفوفات المؤشرات للكائنات , وهي تصميمات تتيح لك أسلوبا أكثر مرونة للتعامل مع عدة كائنات من وضعها هي ذاتها في مصفوفات (علي سبيل المثال سوف يبين لك البرنامج fersort.cpp في هذا المقال كيف يمكن ترتيب عدة كائنات بترتيب ننشئ مصفوفة مؤشرات لكائنات الفئة person .
ptrobjs.cpp
// ptrobjs.cpp
// array of pointers to objects
#include <iostream.h>
#include <conio.h>
class person // class of persons
{
protected:
char name[40]; // person's name
public:
void setName() // set the name
{
cout << "Enter name: ";
cin >> name;
}
void printName() // get the name
{
cout << "\n Name is: "
<< name;
}
};
void main()
{
person* persPtr[100]; // array of pointers to persons
int n = 0; // number of persons in array
char choice;
do // put persons in array
{
persPtr[n] = new person; // make new object
persPtr[n]->setName(); // set person's name
n++; // count new person
cout << "Enter another (y/n)? "; // enter another
cin >> choice; // person?
}
while( choice=='y' ); // quit on 'n'
for(int j=0; j<n; j++) // print names of
{ // all persons
cout << "\nPerson number " << j+1;
persPtr[j]->printName();
}
getche();
} // end main()
الفئة المبينة لها عنصر بيانات واحد name يحوي مصفوفة لتخزين اسم الشخص وتقوم الدالة الأصلية بإنشاء مصفوفة مؤشرات persPtr من مائة عنصر لاحتواء المؤشرات لكائنات الفئة بالأمر :
Person* persPtr[10];
عن طريق الدوارة do تنشئ الدالة الكائن الأول , مستخدمة المؤثر new ثم تستثير الدالة setName() الخاصة بالكائن لإدخال الاسم وثم يسأل البرنامج عن رغبة المستخدم في إدخال إسم جديد وفي حالة الإيجاب ينشأ كائن ثان ويدخل فيه الاسم , وهكذا إلي أن يدخل المستخدم حرف n بعد ذلك تنفذ دوارة for التي تستثير دالة الإظهار في الكائنات واحدا بعد الأخر .
وقد استثيرت دوال الكائن دون اللجوء باسمه عن طريق الأوامر :
persPtr[n]->setName();
persPtr[n]->printName();
ولعل هذا البرنامج يكون قد أعطاك فكرة عن مدي المرونة في استخدام المؤشرات بدلا من أسماء الكائنات عند التعامل مع أعداد كبيرة من الكائنات .
تعليقات
إرسال تعليق