المؤشر this في ++C

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;

دون أن نخشي خطر نسخ العبارات النصية


التسميات: