יום רביעי

this


מה משמעות המילה this?  this מייצגת מצביע לאובייקט אליו המתודה שייכת.
נראה דוגמא בה נדגים את השימוש ב-this.
הדוגמא מראה שני שימושים בהם this מועילה:
1. במצב בו שם פרמטר לפונקציה זהה לשם משתנה של הפונקציה. במקרה זה הפרמטר "מכסה" את המשתנה. נפתור את הבעיה תוך שימוש ב-this (ראו למטה - שורת הקוד בכתום). 
2. מצב בו דרוש pointer לאובייקט הלוקלי. נראה מתודה שצריכה להחזיר pointer  כזה. (מודגש בצהוב).
הנה הדוגמא ואחריה הסבר.

  1. /*
  2.  * this.cpp
  3.  *
  4.  *  Created on: Mar 20, 2012
  5.  *      Author: ronen halevy
  6.  */

  7. #include <iostream>
  8. using namespace std;


  9. class Example{
  10. public:
  11. int a;
  12. int b;
  13. Example(int a, int b);
  14. Example *check_bigger_a(Example &ex);
  15. };

  16. Example::Example(int a, int b){this->a = a; Example::b =b;}

  17. Example *Example::check_bigger_a(Example &ex){
  18. if(a > ex.a)
  19. return this;
  20. else
  21. return &ex;
  22. }

  23. int main(){
  24. Example ex1(1,2);
  25. Example ex2(3,4);
  26. Example *ex3;
  27. ex3 = ex1.check_bigger_a(ex2);
  28. cout << ex3->a;
  29. }

הסבר:
נתיל עם בעית כסוי המשתנה ע"י פרמטר:
שורה 20: זה ה-constructor. 
מה היה קורה אם הוא היה נראה כך:
Example::Example(int a, int b){a = a;  b =b;}

תשובה: ב- C++ זהו באג. a ו-b לא יקבלו  את ערכי הפרמטרים. הסיבה: בגלל השמות הזהים, הקומפיילר לא מבחין בין ה- class member לבין הפרמטר שהוא automatic variable.
ישנם מספר פתרונות לבעיה:
1. לדאוג שלפרמטרים יהיה שם אחר, למשל:

Example::Example(int _a, int _b){a = _a;  b = _b;}

2. להשתמש בשם ה-class שיזהה את ה-class members באופן הבא:

Example::Example(int a, int b){Example:a = a;  Example:b = b;}

3. להשתמש ב-this:

Example::Example(int a, int b){this->a = a;  this->:b = b;}

קיים גם פתרון נוסף - שימוש ב-initialization list. זה מתאים רק ל-constructors, אבל במקרה הדוגמא הנ"ל היא של contructor:
Example::Example(int a, int b): a(a), b(b){}

לכל המעונין - הנה קישור לפוסט על initialization list.

שורה 20 מדגימה שימוש בפתרונות 2 ו-3. הנה היא מועתקת שוב:
Example::Example(int a, int b){this->a = a; Example::b =b;}


שימוש  נוסף של this מודגם בשורה 24. 
נעתיק שוב הנה את שורות 22-27:



  1. Example *Example::check_bigger_a(Example &ex){
  2. if(a > ex.a)
  3. return this;
  4. else
  5. return &ex
  6. }



בשורות הנ"ל, המתודה משווה בין שני ex.a, כאשר ex הוא אובייקט שמועבר כפרמטר, לבין המשתנה הלוקלי a. במתודה מחזירה את המצביע לאובייקט שה-a שלו גדול יותר.
שורה 3: במקרה שהאובייקט הלוקלי גדול יותר, היא מחזירה את this.


ונעבור לפונקציה המפעילה -main. היא מועתקת הנה:

  1. int main(){
  2. Example ex1(1,2);
  3. Example ex2(3,4);
  4. Example *ex3;
  5. ex3 = ex1.check_bigger_a(ex2);
  6. cout << ex3->a;
  7. }

שורות 2-3: יוצרים שני אובייקטים של Example.
שורה 4: יוצרים pointer מסוג Example.
שורה 5: מפעילים את המתודה check_bigger_a של האובייקט ex1. מכאן ש-this יצביע על ex1.
המצביע של האובייקט שה-data member a שלו גדול יותר, יכנס לתוך ex3.
שורה 6: הדפס את ex3->a. מה יהיה הפלט? התשובה: 3.

אין תגובות:

הוסף רשומת תגובה