בקשר לחידה של אלדד-

annefan

New member
בקשר לחידה של אלדד-

שאלתי את השאלה הזו בקבוצת comp.lang.c++.moderated, עם ניתוח אפשרי שלי, כמו שכתבתי כאן. נכון לעכשיו, ענה עליה Victor Bazarov (פעיל מאוד בקבוצה הזו, וקפדן לא נורמלי...). אם זה מעניין את מישהו, הנה הקישור. החידוש העיקרי מבחינתי היתה העובדה ש-this עובר cast לפי המקום שבו הוא בשימוש. תודה אלדד!
 

annefan

New member
להסביר מה?

אחרי שהבנתי מה שהבנתי וקיבלתי אישור מהקבוצה, אני מניח שזה מה שאמרת לגבי הטפוס של this. מה שבטוח לא נכון, זה שהפיכת PrintAndDelete לוירטואלית תפתור את הבעיה.
 

ברנדל

New member
למה לא?

אם תגדיר את PrintAndDelete וירטואלית אז ה delete יפעל על this שמוגדר בבן ולכן הבן ישתחרר כמו שצריך.
 

דריזט

New member
זה לא מספיק להפוך אותה לוירטואלית

צריך גם לממש אותה בבן. הקוד הבא מדגים את הדליפה:
#include <iostream> using namespace std; class CDummy { public: CDummy() {cout <<"CDummy constructor.\n"; } ~CDummy() {cout <<"CDummy destructor.\n"; } }; class CBase { public: virtual void PrintAndDelete() { cout <<"CBase::printAndDelete().\n"; delete this; } }; class CDerived : public CBase { CDummy d; public: //See what happens if you comment the function out virtual void PrintAndDelete() { cout <<"CDerived::printAndDelete().\n"; delete this; } }; int main() { CBase *b = new CDerived; b->PrintAndDelete(); getchar(); }​
 

ברנדל

New member
אתה לא מעודכן

אני מדבר על זה שבבן זה מוגדר גם (וזה גם מה שרשמתי בשרשור ההוא). נדמה לי שבדוגמא שנתת אתה לא מדגים דליפה, כי אין! אתה קורא לוירטואלית שמוגדרת בבן, ולכן זו של הבן תיקרא וה this יהיה ב cast של הבן.
 

דריזט

New member
אם כך, אין מחלוקת ../images/Emo13.gif

התכוונתי שאת הדליפה רואים בצורה ברורה (אין קריאה להורס של האיבר d) אם משמיטים את מימוש הפונקציה בבן.
 

annefan

New member
הדוגמא שלך לא טובה

אתה משתמש במצביע לבן. אין משהו חדש בזה שזה יכול ליצור בעיות.
 

דריזט

New member
לא טובה מאיזו בחינה?

בסה"כ הדגמתי בפשטות את אי-הריסתו של הבן במקרה ש delete this לא נקרא דרכו. אם אתה מתכוון לכך שבכל מקרה אסור/לא כדאי למחוק אובייקט מתוך עצמו, אני מסכים. לרוב ניתן לתכנן את התוכנית בצורה אחרת.
 

annefan

New member
מבחינת מה שכתבתי בהודעה...

אתה משתמש במצביע לסוג אב המצביע לסוג הבן, והפונקציות לא וירטואליות. בחידה של אלדד, הכל לכאורה היה בסדר. היה רק מצביע לבן, הפונקציה הנקראת אמנם לא היתה וירטואלית, אבל גם כשהפכנו אותה לוירטואלית, עדיין נשארה הבעיה, כי היא עצמה קראה לפונקתיה לא וירטואלית (DTOR אצל אלדד, ppp אצלי). לגבי delete this כשלעצמו, זה FAQ.
 

annefan

New member
זו הנקודה

גם אם היא היתה וירטואלית, עדיין היא מוגדרת רק באב. כיוון שכך הטיפוס של this בתוך הפונקציה הוא CBase. כשאתה קורא על האובייקט הזה delete והוא לא וירטואלי, יופעל delete על CBase ולא על CDerived. ולכן, עלול להיות leak.
 

ברנדל

New member
ברור

זה בדיוק מה שאמרתי אז , אם זה לא היה ככה זה אומר שהפוינטרים שהפונקציה מתיחסת אליהם מקבלים את ה cast שלהם בזמן ריצה. וכפי שהזכרתי , פוינטרים לא יושבים ב vtable זה לא פונקציות. קיצר תם ונשלם.
 
למעלה