الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

كلمة This

مغلق
بدأه بن حسن في 27 مارس 2005 · 7 رد · 1,879 مشاهدة · في الأسئلة المجابة
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم ورحمة الله وبركاته

مامعنى كلمة This

نجدها كثيرا في أكواد السي

ياريت أخ يوضحهالنا

أسألكم الدعاء لأبي و أمي

#2

لما تكون في داخل member function في class, كلمة this هو مؤشر (pointer) لكائن اللذي نتصرف معه حاليا ..

مثلا,

class Point
{
public:
	int x;
	int y;

	void setX( int nx )
	{
  x = nx;
	}

	void setY( int ny )
	{
  y = ny;
	}
};

int main()
{
	Point loc;
	loc.setX( 4 );
	loc.setY( 2 );

	return 0;
}

لاحظ في داخل الـ

void setX( int nx )

هناك سطر:

x = nx;

نعرف أن الـ nx هي البارامتر المرسل للفنكشن, و لكن ما هي هذه الـ x؟!

x تسمى instance variable يعني متغير يتبع كائن معين من الصنف Point, هذا الكائن لديه متغيرات داخلية من ضمنها المتغير x, و عندما تنادي

loc.setX(4)

فهنا setX تعرف انك تتعامل مع الكائن loc و الـ x هنا هي الـ x التابعة للـ loc.

طبعا لو كان لديك كائن آخر باسم آخر, مثلا

Point pos;

فإن

pos.setX( 10 );

سينادي setX و لكن setX هذه المرة سيتعامل مع pos, فالـ x اللتي في داخله هي الـ x التابعة للـ pos.

كل ما أردت قوله من ذلك الكلام هو ان المتغيرات في الكلاس تعتمد على وجد كائنات من هذا الكلاس (الصنف او الفئة) و عندما تكتب سطرا مثل:

x = nx;

فأنت تتعامل من كائن (instance, object) من هذا النوع او الكلاس. يعني انت تكتب و في بالك ان هناك كائن محدد سيقوم باستدعاء هذا الـ function, و إلا, ما هي الـ x؟! فالـ x ليست متغيرا واحدا تابع للكلاس, و لا تستطيع الإشارة إليها بمجرد اسم الكلاس, يعني

Point.x مثلا .. اللهم إلا إذا كان x عبارة عن static variable.

فماهية الـ x تعتمد على الكائن اللذي قام باستدعاء الـ function, فالـ x هنا هي الـ x التابعة للكئن اللذي نتعامل معه حاليا.

هذا الكائن, نستطيع كما رأينا أن نشير الى عناصره بمجرد كتابة اسم المتغير, و لكن كيف نشير الى الكائن نفسه؟

هذا هو الغرض من this, فهو مؤشر الى الكائن.

لو قلت

this->x = nx;

فانت تشير الى المتغير x التابع للكائن الحالي, و هذا السطر هو بالظبط مثل:

x = nx;

لا يوجد فرق إطلاقا.

#3

وعليكم السلام ورحمة الله

:)

بما إنك أصلاً "فيبيهاوي" قبل ما تكون "سيهاوي" :)

ف this = me

لكن خلي بالك This غير this

إنت في السي فلازم تاخد بالك

#4

السلام عليكم :lol: .

لنعتبر تعريف الكلاس التالي في سي++ كمثال:

class TPoint
{
public:
   //x,y is menbers
   int x;
   int y;

   // SetPoint is a Methode
   void SetPoint(int nx, int ny)
    {
      x= nx;
      y= ny;
    }
};

عند تعريف متغيرين a و b من هذه الكلاس TPoint, فإن المصرف سيحجز مساحة في الذاكرة لكل عنصر x و y لكل من a و b حيث أنه سيكون لكل منهما نسخة خاصة به لx ول y. لكن الدالة SetPoint لن تحجز لها من الذاكرة إلا مساحة واحدة فقط و ستستعملها كل متغيرات الكلاس TPoint:

1000...........1001/1002..........1003/1004...........1005/1006..........1007
|______ x_______| |______ y_______||______ x_______| |______ y_______|
|______________a _______________||______________b________________|

40060.............
|___ SetPoint___|

فالدالة SetPOint لن تكون منها إلا نسخة واحدة فقط . و عند كتابة:

a.SetPoint(0,2);
b.SetPoint(3,5);

فإن كلا من a أو b يستدعيان نفس الدالة.

لكن كيف ستعرف هذه الدالة من هو المتغير الذي استدعاها هل هو a أم لb؟

كيف ستتعامل مع العناصر x و y؟

هذا هو عمل الؤشر this حيث أن لكل كلاس يقوم المصرف بتعريف عنصر لها من صنف مؤشر و يسميه this عند تعريف أي متغير للكلاس فإن this سيحتوي على عنوان الكلاس في الذاكرة.

وعند استدعاء مناهج الكلاسات فإن المصرف يقوم بإدراج باراميتر مخفي في لائحة الباراميترات للمنهج و هو this ويعيد كتابتها بحيث يضيف أمام كل عنصر للكلاس هذا المؤشر.. سأوضح بمثال عن هذا عند استدعاء المنهج SetPoint:

   void SetPoint(TPoint* this,  int nx, int ny)
    {
      this->x= nx;
      this->y= ny;
    }

هكذا فإن عند أي استدعاء لمنهج من مناهج الكلاس فأن المنهج يستطيع الوصول إلى العناصر المستهدفة للكلاس اللتي استدعت المنهج.. :lol: .

أرجو أن يصحح الإخوة ما ذكرت لإن كان فيه أخطاء , فأنا مبتدئ في هذه اللغة :)

سأتغيب عن المنتدى وستكون لي زيارات خفيفة بين الحين و الحين

يا صاحب الهم إن الهم منفرج.....................أبشر بخير فإن الفارج الله.

اليأس يقطع أحيانا بصاحبه..........................لا تيأس فإن الكافي الله.

الله يحدث بعد العسر ميسرة.........................لا تفزعن فإن الصانع الله.

إذا بليت فثق بالله وارض به...................فإن الذي يكشف البلوى هو الله.

و الله ما لك غير الله من أحد.......................فحسبك الله في كل لك الله

أخوكم مراد

27_06_06_05_21_41_1151410901logo_adl_wal_ihsan.jpg

#5

السلام عليكم

أخي ikossan العزيز في الدالة التالية :

void SetPoint(TPoint* this,  int nx, int ny)
   {
     this->x= nx;
     this->y= ny;
   }

لست بحاجة لكتابة المؤشر this كبارميتر للدالة لانه وبسبب بسيط فان المؤشر this هومؤشر ثابت لأي كائن object معرف من الclass TPoint .أي انه دائما مؤشر ثابت يشير للكيان الممر ضمنا للدالة.

انظر الدالة التالية

void SetPoint(  int nx, int ny)
   {
     this->x= nx;
     this->y= ny;
   }

جربها واذا من خطأ فصححلي بارك الله فيك.

اللهم علمنا ما ينفعنا وأنفعنا بما علمتنا أنك أنت العليم الحكيم

سبحان الله وبحمده سبحان الله العظيم

لاحول ولاقوة الا بالله( كنز من كنوز الجنة ).

#6

كلامك صحيح يا أخي السهم الناري

لكني لم اقصد أن المبرمج هو الذي يجب كتابة الباراميتر this !!

ما قصدته أن المصرف في لغة C++ يقوم بإدراج متغير إسمه this من صنف k * const لكل instance من صنف كلاس k , حيث ان this يحتوي بصفة تابثة طيلة عمر ال instance على عنوانها في الذاكرة .

جرب هذا الكود :D

#include <iostream.h>
//---------------------------------------------------------------------------

class TPoint
{
public:
   int x,y;
   void showxy( void);
};

void TPoint::showxy(void)
 {
   printf("Adress of x is:\t 0x%x .",&x);
   printf("\nAdress of y is:\t 0x%x .", &y);
   printf("\nadress of 'this' is:\t 0x%x .\n\t Is the same as adress of x;)",  this);
   printf("\nadress of the showxy() is 0x%x .\n\t and is the same as all instance of class Tpoint\n\n\n",&showxy);
 }


int main(int argc, char* argv[])
{

  TPoint p,q,r;
  cout << "********** p point:*****************\n";
  p.showxy();
  cout << "********** q point:*****************\n";
  q.showxy();
  cout << "********** r point:*****************\n";
  r.showxy();
  system("pause");
  return 0;
}
//---------------------------------------------------------------------------

في كل منهج من مناهج الكلاس فالمصرف لا يحجز لها إلا نسخة واحدة في االذاكرة ( لاحظ عنوان الذاكرة للمنهج showxy).

على عكس العناصر, فإن لكل Instance نسخة خاصة لها في الذاكرة( لاحظ عناوين الذاكرة لكل من x و y).

فعند استدعاء p.showxy أو q.showxy أو r.showxy فإننا نستدعي نسخة واحدة لهذا المنهج و ليس نسخ من الكود مختلفة في الذاكرة.

فكيف ستتعرف هذه الإجرائية showxy على الكلاس التي استدعتها؟ هل p أم q أم r؟؟

هذا هو دور المؤشر this حيث ان المصرف the compiler يقوم بتكويد هذا المنهج بحيث يعيد كتابته على هذا النحو:

void TPoint::showxy(TPoint* const this)
 {
   printf("Adress of x is:\t 0x%x .",&(this->x));
   printf("\nAdress of y is:\t 0x%x .", &(this->y));
   printf("\nadress of 'this' is:\t 0x%x .\n\t Is the same as adress of x;)",  this);
   printf("\nadress of the showxy() is 0x%x .\n\t and is the same as all instance of class Tpoint\n\n\n",&showxy);
 }

أنا لا اقول أنك يجب أن تكتب هذا المنهج بهذه الصيغة لكن فقط وضحت كيف يقوم بها المصرف بطريقة آلية ويقوم بعدها بإخفاء تعريف this.

فإذا ما عرفت باراميتر جديد يحمل نفس الإسم this فإن المصرف سيعطي رسالة خطأ!!!

هذا مثال يبين طريقة استعمال this

#include <iostream.h>
//---------------------------------------------------------------------------

class TPoint
{
public:
   int x,y;
   void setxy(int x, int y);
   void showxyAdress( void);
   TPoint& getx(void);
   TPoint& gety(void);
   void showxy(void);
};

void TPoint::showxyAdress(void)
 {
   printf("Adress of x is:\t 0x%x .",&x);
   printf("\nAdress of y is:\t 0x%x .", &y);
   printf("\nadress of 'this' is:\t 0x%x .\n\t Is the same as adress of x;)",  this);
   printf("\nadress of the showxy() is 0x%x .\n\t and is the same as all instance of class Tpoint\n\n\n",&showxy);
 }

void TPoint::setxy(int x, int y)
{
// utility of this
 this->x= x;
 this->y= y;
}


TPoint& TPoint::getx(void)
{
 cout << "\nenter x:\t";
 cin >> x;
 return *this;
}

TPoint& TPoint::gety(void)
{
 cout << "\nenter y:\t";
 cin >> y;
 return *this;
}

void TPoint::showxy(void)
{
 cout << "\n(" << x << ';' << y << ") .\n";
}


 int main(int argc, char* argv[])
{

  TPoint p;
  // utility of this
  p.getx().gety().showxy();

  cout << "\n\nset point: x = 1 and y = 5";
  p.setxy(1,5);
  p.showxy();
  system("pause");
  return 0;
}
//---------------------------------------------------------------------------

B)

تم تعديل هذه المشاركة بواسطة ikossan في 30 مارس 2005 في 22:05

سأتغيب عن المنتدى وستكون لي زيارات خفيفة بين الحين و الحين

يا صاحب الهم إن الهم منفرج.....................أبشر بخير فإن الفارج الله.

اليأس يقطع أحيانا بصاحبه..........................لا تيأس فإن الكافي الله.

الله يحدث بعد العسر ميسرة.........................لا تفزعن فإن الصانع الله.

إذا بليت فثق بالله وارض به...................فإن الذي يكشف البلوى هو الله.

و الله ما لك غير الله من أحد.......................فحسبك الله في كل لك الله

أخوكم مراد

27_06_06_05_21_41_1151410901logo_adl_wal_ihsan.jpg

#7

بارك الله فيك اخي مراد واهلا بكمعنا هنا.

حقيقة النقاش معك ممتع واشكرك على تقبل ملاحظتي بصدر رحب.

والى القاء.

اللهم علمنا ما ينفعنا وأنفعنا بما علمتنا أنك أنت العليم الحكيم

سبحان الله وبحمده سبحان الله العظيم

لاحول ولاقوة الا بالله( كنز من كنوز الجنة ).

#8

ياسلااااااام

إيه الحلاوة دي

كل الشرح ده عشاني انا

جزاكم الله كل خير

أخ نحراوي

انا فعلا كنت فيبيهاوي بس قلت اتعلم شوية سي

و الموضوع في أوله صعب

لكن إن شاء الله ربنا يعينا

وكما قال الشاعر

لا يأس مع التاكس :D

شكرا لكم جميعا

أسألكم الدعاء لأبي و أمي

هذا الموضوع مغلق.

مواضيع مشابهة