المؤشر this في ++C
المؤشر this
لكل دالة منتمية لفئة ما اتصال بمؤشر خفي يسمي المؤشر this يحتوي علي عنوان الكائن الذي ينشأ من هذه الفئة , بحيث يمكن علي الدوام معرفة موضع أي كائن من الذاكرة ولبيان ذلك نقدم لك برنامجا صغيرا يظهر دور هذا المؤشر .
where.cpp
// where.cpp
// the this pointer
#include <iostream.h>
class where
{
private:
char charray[10]; // occupies 10 bytes
public:
void reveal()
{ cout << "\nMy object's address is " << this; }
};
void main()
{
where w1, w2, w3; // make three objects
w1.reveal(); // see where they are
w2.reveal();
w3.reveal();
}
تنشئ الدالة الأصلية ثلاثة كائنات من الفئة where ثم تسأل من كل كائن أن يعلن عن عنوانه , باستخدام دالته reveal () وحيث إن عنصر البيانات في الكائن (الذي لم نستخدمه ) هو مصفوفه من 10 محارف , فإن الكائنات تكون متباعدة بمقدار 10 بايتات ] يمكن حساب الفرق بين العناوين بعد تحويلها للنظام العشري [ .
الوصول إلي عنصر للكائن
حينما تستدعي دالة منتمية , فإنها تظهر للوجود محملة بالمؤشر this متضمنا عنوان الكائن الذي استدعاها , وهذا المؤشر يمكن معاملته كأي مؤشر عادي , ومن ثم يمكن استغلاله للتعامل مع أي عنصر من عناصر الكائن الذي يشير إليه , كما يتضح إليك من البرنامج التالي .
dothis.cpp
// dothis.cpp
// the this pointer referring to data
#include <iostream.h>
class what
{
private:
int alpha;
public:
void tester()
{
this->alpha = 11; // same as alpha = 11;
cout << this->alpha; // same as cout << alpha;
}
};
void main()
{
what w;
w.tester();
}
هذا البرنامج يطبع ببساطة العدد 11 . لاحظ أن الدالة tester() تصل للمتغير alpha عن طريق الصيغة this-> alph . هذه الصيغة لا تختلف عن مناداه المتغير باسمه مباشرة , alpha وليس من قيمة سوي بيان دور المؤشر this في البرمجة .
إعادة قيمة باستخدام this
الاستخدام الأكثر واقعية هو أن يستخدم المؤشر المذكور في إعادة القيم من الدوال المنتمية والمؤثرات زائدة التحميل .
تذكر أننا في البرنامج assign.cpp لم نستطع أن نعيد قيمة بالإشارة لأن الكائن كان محليا بالنسبة للدالة التي تعيد القيمة . والأن نعدل البرنامج لنتمكن من الوصول لهذه النتيجة عن طريق المؤشر this .
assign2.cpp
// assign2.cpp
// returns contents of the this pointer
#include <iostream.h>
class alpha
{
private:
int data;
public:
alpha() // no-arg constructor
{ }
alpha(int d) // one-arg constructor
{ data = d; }
void display() // display data
{ cout << data; }
alpha& operator = (alpha& a) // overloaded = operator
{
data = a.data; // not done automatically
cout << "\n... and UCS lives again. (invoked)";
return *this; // return copy of this alpha
}
};
void main()
{
alpha a1(37);
alpha a2, a3;
a3 = a2 = a1; // invoke overloaded =
cout << "\na2="; a2.display(); // display a2
cout << "\na3="; a3.display(); // display a3
}
التغيير في هذا البرنامج أننا تمكنا من استخدام العبارة التي تستخدم الإعادة بالإشارة :
Alpha& operator(alpha& a);
بدلا من
Alpha operator(alpha& a);
مع التعبير عن القيمة المعادة باستخدام صيغة المؤشرات ؛ this * . وبذلك نكون قد حققنا غرضنا من عم اللجوء للنسخ عند إعادة القيم .
مراجعة برنامج strimem.cpp
بنفس المنطق سوف نعيد صياغة البرنامج strimem.cpp علي الصورة التالية :
strimem2.cpp
// strimem2.cpp
// memory-saving String class
// the this pointer in overloaded assignment
// UCS Laboratories
#include <iostream.h>
#include <string.h> // for strcpy(), etc
#include <conio.h> // for getch()
class strCount // keep track of number
{ // of unique strings
private:
int count; // number of instances
char* str; // pointer to string
friend class String; // make ourselves available
public:
strCount(char* s) // one-arg constructor
{
int length = strlen(s); // length of string argument
str = new char[length+1]; // get memory for string
strcpy(str, s); // copy argument to it
count=1; // start count at 1
}
~strCount() // destructor
{
delete[] str; // delete the string
}
};
class String // String class
{
private:
strCount* psc; // pointer to strCount
public:
String() // no-arg constructor
{
psc = new strCount("NULL");
}
String(char* s) // 1-arg constructor
{
psc = new strCount(s);
}
String(String& S) // copy constructor
{
cout << "\nCOPY CONSTRUCTOR";
psc = S.psc;
(psc->count)++;
}
~String() // destructor
{
if(psc->count==1) // if we are its last user,
delete psc; // delete our strCount
else // otherwise,
(psc->count)--; // decrement its count
}
void display() // display the String
{
cout << psc->str; // print string
cout << " (addr=" << psc << ")"; // print address
}
String& operator = (String& S) // assign the string
{
cout << "\nASSIGNMENT";
if(psc->count==1) // if we are its last user,
delete psc; // delete our strCount
else // otherwise,
(psc->count)--; // decrement its count
psc = S.psc; // use argument's strCount
(psc->count)++; // increment count
return *this; // return this object
}
};
void main()
//UCS Laboratories
{
String s3 = "When the fox preaches, look to your geese.";
cout << "\ns3="; s3.display(); // display s3
String s1, s2; // define Strings
s1 = s2 = s3; // assign them
cout << "\ns1="; s1.display(); // display it
cout << "\ns2="; s2.display(); // display it
getch(); // wait for keypress
}
وقد أصبح الإعلان عن مؤثر التخصيص علي الصورة :
String& operator = (string& s)
ويكون بإمكاننا استخدام صيغة التخصيص المتسلسل :
S1=s2=s3;
دون أن نخشي خطر نسخ العبارات النصية
جميل جداً ......
ردحذفوربنا يوفقك ...