ABA


"|++C| שאלה בנושא ירושות"
גירסת הדפסה        
קבוצות דיון פיתוח, תיכנות ובניית אתרים נושא #15905 מנהל    סגן המנהל    מפקח   Winner    צל"ש   מומחה  
אשכול מספר 15905
Zippo 
חבר מתאריך 26.5.02
7921 הודעות
   19:12   20.05.10   
אל הפורום  
  |++C| שאלה בנושא ירושות  
 
איך אפשר לפתור בעזרת ירושות (ולא טמפלטס) שינוי סוג ממבר במחלקה?
השאלה קצת לא ברורה, וההסבר הכי טוב יהיה המקרה בו נתקלתי.

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

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

איך אני יכול להשתמש ברשימה הפשוטה כבסיס לירושה של הרשימה הממויינת עם הפונקציות השונות על האיברים?

כדי להמחיש את הבעיה:


class SimpleList
{
private:
...struct Node
...{
......SimpleClass* object;
......Node* next;
...};
...Node* head;
Public:
...some simple methods...
};
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
class ComplicatedList
{
private:
...struct Node
...{
......ComplicatedClass* object;
......Node* next;
...};
...Node* head;
Public:
...some simple methods...
...complicated methods addition...
};

אשמח לתשובה מהירה.
תודה רבה!


                                שתף        
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד

  האשכול     מחבר     תאריך כתיבה     מספר  
  לא הבנתי כל כך VeNom  20.05.10 20:49 1
     יש פה כביכול 2 ירושות. Zippo  20.05.10 23:28 2
         אממ VeNom  21.05.10 00:23 3
             לא זאת הבעיה. Zippo  21.05.10 00:37 4
  כן, תירש מהמחלקה האבסטרקטית ldan192  21.05.10 12:21 5
     אבל ה-node הוא לא אותו node Zippo  21.05.10 13:46 6
         בגלל זה אמרתי, אם אתה מחפש יותר להתחכם ldan192  21.05.10 14:18 7
             אתה רוצה שה-node יכיל גם את האוביקט החדש Zippo  21.05.10 14:50 8
                 יכול להיות שגם אני לא הבנתי אותך. אתה רוצה מה בדיוק? ldan192  21.05.10 16:22 9
                     לא, ממש לא מחלקה ש''עוטפת'' Zippo  21.05.10 17:17 10
                         שוב, לא בטוח באיזה שלב בדיוק יש לך שכפול קוד ldan192  21.05.10 18:28 11
                             אלא אם אני כן הבנתי אותך ואתה אומר ldan192  21.05.10 18:36 12
                                 מקודם כנראה הבנת אותי, אבל אי אפשר לבצע Hiding Zippo  22.05.10 21:23 13
                                     הבנתי, אז למרות שזה לא אלגנטי ונקי, מה רע במימוש ldan192  24.05.10 15:46 14
                                         אם הייתי יכול להשתמש בטמפלטס, העולם היה ורוד יותר. Zippo  24.05.10 19:32 15
  אממ לא קראתי את כל התגובות אבל פאביו ג'וניור 25.05.10 12:56 16
  לא הבנתי, למה פונקציה וירטואלית פשוטה לא פותרת את הבעיה mega-killer 05.06.10 17:33 17
     כי אני לא רציתי רק פונקציה בעלת שם זהה וביצוע שונה. Zippo  05.06.10 21:22 18
         אין שום בעיה לבצע לו Hiding ldan192  05.06.10 22:59 19
             אבל הפונקציות יעבדו אותו דבר? Zippo  06.06.10 01:16 20
                 הראתי hiding של שדה, אבל באותה מידה אפשר לבצע ldan192  07.06.10 15:51 21
                     זאת בדיוק הבעיה. אני לא רוצה לבצע היידינג של מתודה Zippo  07.06.10 20:30 22
                         עכשיו הבנתי מה אתה רוצה! קצת מוזר לי כי הבנתי ממך ldan192  08.06.10 00:54 23
                             אחלה! אני חושב שהבנתי. Zippo  11.06.10 05:13 24
                                 יש אפשרות עם templating :\ אפשר גם לבצע downcasting ldan192  11.06.10 12:50 25
                                     לא לחוץ. טוב לידע כללי, אבל את התרגיל שבשבילו הייתי Zippo  11.06.10 14:51 26
                                         כן, אני מתאר לעצמי. וחשבתי על זה קצת ולדעתי ldan192  11.06.10 17:35 27

       
VeNom  לחץ כאן להצגת דירוג המשתמש
חבר מתאריך 7.6.02
7922 הודעות, 1 פידבק
   20:49   20.05.10   
אל הפורום  
  1. לא הבנתי כל כך  
בתגובה להודעה מספר 0
 
   מה אתה רוצה..אבל בגדול נראה לי שאני מבין את הכיוון..
אתה רוצה שהטיפוס של הרשימה יהיה מסוג node..עכשיו אתה כן כותב את הclass node הזה עכשיו..
והטיפוס החדש שלך יהיה משהו כזה:

class new : public node
{
}

אני לא זוכר את הסינטקס של cpp
אבל בגדול אם לזה התכוונת אז יש שימוש בהורשה למטרת רשימה פולימורפית..
ומכיוון שהטיפוס החדש שלך ירש מ node
הוא יהיה סוג של node


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Zippo 
חבר מתאריך 26.5.02
7921 הודעות
   23:28   20.05.10   
אל הפורום  
  2. יש פה כביכול 2 ירושות.  
בתגובה להודעה מספר 1
 
הרשימה המשוכללת יורשת מהרשימה הפשוטה.
וה node ברשימה המשוכללת יורש (או סתם מחליף) את ה- node ברשימה הפשוטה.

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


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
VeNom  לחץ כאן להצגת דירוג המשתמש
חבר מתאריך 7.6.02
7922 הודעות, 1 פידבק
   00:23   21.05.10   
אל הפורום  
  3. אממ  
בתגובה להודעה מספר 2
 
   שאתה יורש מהרשימה הפשוטה אתה מקבל את כל הממברים + פונקציות ממי שירשת(יש לך אופציה לעשות העמסה שלהם)..את זה אני יודע שאתה יודע..
אם אתה מקבל את כל הממברים אז בעצם אתה מקבל גם את ה node של האבא ממנו ירשת..
ולכן הצעתי לך פתרון שנראה לי..
אתה מכין class node קבוע כלשהו..שיהיה אבסרקטי..והוא יהיה קבוע..
בכל רשימה יהיה לך ממבר של node כאיבר ברשימה..
עכשיו ברגע שתירש ותשכלל את הרשימה גם שם יהיה לך את ה node הזה..
וכל היופי כאן הוא שאתה תממש כל פעם בהתאם לצורך class חדש שהוא יירש מ node והוא בעצם יהיה סוג של node..כלומר לא יהיו לך שינויים ברשימות..וזה בעצם יוצר לך אופציה של רשימה פולימורפית..

אני מקווה שהבנתי אותך שוב פעם..כי אין יותר מדי לאן ללכת ברשימות מקושרות..וכי אני זוכר שאני עשיתי את הקורס אז הייתי צריך לממש משהו כזה..


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Zippo 
חבר מתאריך 26.5.02
7921 הודעות
   00:37   21.05.10   
אל הפורום  
  4. לא זאת הבעיה.  
בתגובה להודעה מספר 3
 
הרבה מתודות משתמשות ב-node. אם הוספת איבר לרשימה, או כל מתודה פשוטה אחרת.
ה-node הוא ישות בפני עצמה. יש לה מקום מוגדר על הקוד סגמנט.

אם אני מגדיר node מסוג חדש, בין אם בירושה, בין אם לא, הוא ישב במקום אחר בקוד סגמנט.

כל המתודות ברשימה הנורשת, אם לא שכתבתי אותן, מתייחסות ל-node המקורי שיושב במקום המקורי בקוד סגמנט.

אני רוצה לא להצטרך לשכתב אותן, ובכל זאת, שכל הקוד יתייחס למחלקה החדשה של ה-node החדש.

אגב, זה לא התרגיל, ואפילו לא משהו שחובה לעשות, זה חלק קטן מאד מתרגיל שאני צריך לבצע. ואני רוצה לעשות את זה "כמו שצריך".


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ldan192 
חבר מתאריך 14.9.08
95119 הודעות
   12:21   21.05.10   
אל הפורום  
  5. כן, תירש מהמחלקה האבסטרקטית  
בתגובה להודעה מספר 0
 
ותוסיף 2 טיפוסי "next" (ו-"prev" אם צריך) כאיבר הבא ברשימה מהקושרת.
פעם אחת תוסיף בצורה ממויינת (ע"י שימוש האופרטור)
ופעם שניה תוסיף בצורה לא ממויינת (ע"י שימוש באופרטור שמחזיר תמיד 1/0, תלוי מתי תרצה שיחזיר true).

בסה"כ, זו הדרך הכי בסיסית ופשוטה, יש דרכים יותר מתוחכמות, אבל עדיף שתתחיל מהבסיסיות קודם.


בברכה,
עידן


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Zippo 
חבר מתאריך 26.5.02
7921 הודעות
   13:46   21.05.10   
אל הפורום  
  6. אבל ה-node הוא לא אותו node  
בתגובה להודעה מספר 5
 
ולכן כל פעולה שאני רוצה לבצע על הרשימה עצמה, ואני לא מדבר על השוואה בין האובייקטים בתוך ה-node, אני אצטרך לציין מפורשות לאיזה node אני מתכוון. אם ל- SimpleList::Node.objest או ל- ComplicatedList::Node.objest

מה שאומר שאת אותן פונקציות בדיוק אני אכתוב פעמיים. מה שרציתי להמנע ממנו.

:\


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ldan192 
חבר מתאריך 14.9.08
95119 הודעות
   14:18   21.05.10   
אל הפורום  
  7. בגלל זה אמרתי, אם אתה מחפש יותר להתחכם  
בתגובה להודעה מספר 6
 
אתה יכול להשתמש בקלאס node עם טיפוס int-י (טמפלייט)
ככה שהאופרטור יבצע || עם ה-int וככה יתנהג אחרת.

אפשר גם שכל רשימה תכיל רק כתובת next ו-prev ותכיל בצד את ה-head של הרשימות המקושרות (בדומה למה שהולך בלינוקס).

שוב, יש מליון דרכים למנוע שכפול קוד, השאלה איזו דרך הכי קלה תהיה לך.


בברכה,
עידן


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Zippo 
חבר מתאריך 26.5.02
7921 הודעות
   14:50   21.05.10   
אל הפורום  
  8. אתה רוצה שה-node יכיל גם את האוביקט החדש  
בתגובה להודעה מספר 7
 
וגם את הישן, וע"י FLAG כלשהוא, אינט או בוליאן, אני אדע באיזה משתנה אני משתמש?

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

(או שבכלל לא הבנתי אותך כמו שצריך...)


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ldan192 
חבר מתאריך 14.9.08
95119 הודעות
   16:22   21.05.10   
אל הפורום  
  9. יכול להיות שגם אני לא הבנתי אותך. אתה רוצה מה בדיוק?  
בתגובה להודעה מספר 8
 
לא מחלקה שעוטפת את הנוכחית ויודעת למיין אותה עם האופרטור שלה?
אני לא מבין ממש באיזה קטע נתקעת כנראה...


בברכה,
עידן


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Zippo 
חבר מתאריך 26.5.02
7921 הודעות
   17:17   21.05.10   
אל הפורום  
  10. לא, ממש לא מחלקה ש''עוטפת''  
בתגובה להודעה מספר 9
 
יש לי אובייקט פשוט (במקרה שלי מחרוזות) שאין לי צורך למיין אותם.
להיפך, אני צריך לשמור אותם בסדר ההכנסה.


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

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

את המתודות המשותפות ל2 סוגי הרשימות שיש לי אני לא רוצה לשכפל.
כלומר פונקציות כמו D'tor(), delete(i), getLast(), getHead() etc~
הן זהות ב-2 הרשימות.

איך אני נמנע משכפול הקוד המיותר הזה, ועדיין שומר על כל הפונקציונאליות הנדרשת מכל רשימה?


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ldan192 
חבר מתאריך 14.9.08
95119 הודעות
   18:28   21.05.10   
אל הפורום  
  11. שוב, לא בטוח באיזה שלב בדיוק יש לך שכפול קוד  
בתגובה להודעה מספר 10
 
אבל מקווה שהתוכנית הבאה שכתבתי תענה על השאלות שלך:



#include <iostream>
#include <string>
using namespace std;

#define LIST_ENTRY(ptr, member) \
((Sorted*)((char *)(ptr)-(unsigned long)(&((Sorted*)0)->member)))

typedef struct Head {
struct Head *next, *prev;
} LL;

inline void __add(LL *head, LL *elm) {
elm->next = head->next;
head->next->prev = elm;
head->next = elm;
elm->prev = head;
}
inline void addNext(LL *head, LL *next) {
__add(head, next);
}

inline void addPrev(LL *head, LL *prev) {
__add(head->prev, prev);
}

class Sorted {
public:
Sorted(string str) : mStr(str) {
mSorted.next = mSorted.prev = &mSorted;
mUnSorted.next = mUnSorted.prev = &mUnSorted;
}

virtual ~Sorted() {}
void add(string strIn) {
addPrev(&mUnSorted, &(new Sorted(strIn))->mUnSorted);

for (LL *next = mSorted.next; next->next != mSorted.next; next = next->next)
if (LIST_ENTRY(next, mSorted)->mStr >= strIn) {
addPrev(next, &(new Sorted(strIn))->mSorted);
return;
}
addPrev(&mSorted, &(new Sorted(strIn))->mSorted);
}
void printForEach() {
cout << " -------------- SORTED -------------- \n";
for (LL *next = mSorted.next; next->next != mSorted.next; next = next->next)
cout << LIST_ENTRY(next, mSorted)->mStr << endl;
cout << " ------------- UNSORTED ------------- \n";
for (LL *next = mUnSorted.next; next->next != mUnSorted.next; next = next->next)
cout << LIST_ENTRY(next, mUnSorted)->mStr << endl;
}

LL mSorted;
LL mUnSorted;
string mStr;
};

int main() {
Sorted S("dummy");
S.add("1");
S.add("3");
S.add("2");
S.printForEach();
return 0;
}


[\code]

בצלחה


בברכה,
עידן


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ldan192 
חבר מתאריך 14.9.08
95119 הודעות
   18:36   21.05.10   
אל הפורום  
  12. אלא אם אני כן הבנתי אותך ואתה אומר  
בתגובה להודעה מספר 11
 
שבעצם פונקציית ההוספה קיימת כבר ואיך אפשר לדרוס את האופרטור המקורי בשביל להבדיל למקרים,
אז התשובה שנתתי מקודם עדיין עומדת בעינה (לבצע Hiding בירושה ולהשתמש באופרטור הקודם באיזו דרך שלא תחבר).


בברכה,
עידן


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Zippo 
חבר מתאריך 26.5.02
7921 הודעות
   21:23   22.05.10   
אל הפורום  
  13. מקודם כנראה הבנת אותי, אבל אי אפשר לבצע Hiding  
בתגובה להודעה מספר 12
 
בוא נניח שיש לי שתי רשימות מקושרות שונות עם קוד משוכפל, אבל ניחא, רק כדי שתבין את הרעיון.


int main()
{
...SortedList aList;
...SimpleList bList;
...ComplicatedObject* co = NULL;
...char* str;
...bool noExit = true;
...do
...{
......co = getInputFromUserAndAllocateComplicatedObject();
......cout << "type a string" << endl;
......cin >> str;
......aList.addObject(co);
......bList.addObject(str);
......(aList.getRandObject())->doSomeComplicatedAction();
......cout << bList.getRandObject() << endl;

......cout << "type 0 for exit, 1 for keep running" << endl;
......cin >> noExit;
...}while(noExit)
...return 0;
}

שים לב שהשורות המודגשות באדום, יכולות להיות מבוצעות רק אם אני יודע את סוג הקובץ.
נכון, אני יודע ש-aList מכילה רק אובייקטים מורכבים, ו- bList רק מחרוזות.
אבל אני לא רוצה לבצע דאונקאסטינג (אסור בהגדרת התרגיל), ואני מעדיף להימנע משכפול קוד מיותר...

הבעיה יותר ברורה כעת?


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ldan192 
חבר מתאריך 14.9.08
95119 הודעות
   15:46   24.05.10   
אל הפורום  
  14. הבנתי, אז למרות שזה לא אלגנטי ונקי, מה רע במימוש  
בתגובה להודעה מספר 13
 
בסגנון הבא (לא בדקתי קומפילציה, אבל שתבין את העקרון):

template <int b>
class Integer {
public:
Integer(int x) : num(x);
boolean operator<(const Interger& in) {
if (b || this->num < in.num)
return true;
return false;
}

int num;
}


int main() {
Integer sorted<0>(3);
Integer unsorted<1>(12);
return 0;
}

כמובן שמזה לפתח רשימה מקושרת, ורק במקום להשתמש ב-num תבצע ירושה ו-hiding למתודה הקודמת (ואם לא hiding, פשוט שזה יהיה handler ולאו דווקא דרך ירושה, למרות שאני לא רואה את הסיבה ש-hiding אינו אפשרי).


כמובן שיש עוד 100 דרכים שונות, אבל עדיין זו דרך טובה ויעילה (הכל נעשה בזמן קומפילציה ככה שהאוברהאד על הפיצ'אר הוא כמעט 0)


בברכה,
עידן


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Zippo 
חבר מתאריך 26.5.02
7921 הודעות
   19:32   24.05.10   
אל הפורום  
  15. אם הייתי יכול להשתמש בטמפלטס, העולם היה ורוד יותר.  
בתגובה להודעה מספר 14
 
זה תרגיל לאוניברסיטה, ואסור לנו להשתמש בטמפלטס בתרגיל הזה. :\


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
פאביו ג'וניור

   12:56   25.05.10   
אל הפורום  
  16. אממ לא קראתי את כל התגובות אבל  
בתגובה להודעה מספר 0
 
   אולי תעשה ש complicatedClass ירש מsimpleClass וגם שcomplicatedList ירש מsimpleList...
ככה גם כל הקוד בsimpleList יעבוד כי אתה יורש מsimpleClass וגם תוכל להוסיף את הקוד החדש...

אתה לא מגדיר את Node מחדש בcomplicatedClass... הוא מוגדר בsimpleClass (אם אתה צריך להשתמש בו אז תן לו הרשאת protected או משהו)

אם זה לא הכיוון אולי לא הבנתי את השאלה כ"כ


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
mega-killer
חבר מתאריך 1.8.02
859 הודעות
   17:33   05.06.10   
אל הפורום  
  17. לא הבנתי, למה פונקציה וירטואלית פשוטה לא פותרת את הבעיה  
בתגובה להודעה מספר 0
 
   ?



                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Zippo 
חבר מתאריך 26.5.02
7921 הודעות
   21:22   05.06.10   
אל הפורום  
  18. כי אני לא רציתי רק פונקציה בעלת שם זהה וביצוע שונה.  
בתגובה להודעה מספר 17
 
אלא גם משתנה ממבר במחלקה שהוא מסוג לגמרי שונה.


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ldan192 
חבר מתאריך 14.9.08
95119 הודעות
   22:59   05.06.10   
אל הפורום  
  19. אין שום בעיה לבצע לו Hiding  
בתגובה להודעה מספר 18
 
נניח שבמחלקת הבסיס יש משתנה פרטי x ובאב גם כן אחד כזה.
סתם לצורך העניין:



class A {
public:
A(int xx = 0) : x(xx) {}
virtual boolean operator == (int y) {
return (x == y);
}
private:
int x;
}

class B : public A {
public:
B(int xx = 0) : /*A(xx), */ x(xx) {}
boolean operator == (int z) {
return (x == z+2);
}
private:
int x;
}

לא בדקתי שוב קומפילציה, אבל העקרון אני מאמין שברור.


בברכה,
עידן


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Zippo 
חבר מתאריך 26.5.02
7921 הודעות
   01:16   06.06.10   
אל הפורום  
  20. אבל הפונקציות יעבדו אותו דבר?  
בתגובה להודעה מספר 19
 
אני לא רוצה לשכתב את הפונקציות של האב שמשתמשות בממבר הנ"ל.
ואם אשתמש בפונקציות שכתובות רק במחלקת הבסיס, הממבר שבו הן ישתמשו יהיה הממבר ממחלקת הבסיס, ולא הממבר החדש...


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ldan192 
חבר מתאריך 14.9.08
95119 הודעות
   15:51   07.06.10   
אל הפורום  
  21. הראתי hiding של שדה, אבל באותה מידה אפשר לבצע  
בתגובה להודעה מספר 20
 
hiding של מתודה.
במילים אחרות, כל המתודות בבסיס יהיו ממושות,
וזו שאתה רוצה לדרוס את המימוש שלה תהיה וירטואלית ותמומש גם ביורש.
בצורה הזו יתבצע hiding של האופרטור שאתה צריך.


כמו שאמרתי, יש מליון דרכים לפתרון הבעיה.


בברכה,
עידן


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Zippo 
חבר מתאריך 26.5.02
7921 הודעות
   20:30   07.06.10   
אל הפורום  
  22. זאת בדיוק הבעיה. אני לא רוצה לבצע היידינג של מתודה  
בתגובה להודעה מספר 21
 
כי זה בדיוק אותה פונקציה כמו באבא, ואני רוצה להימנע משכתוב שלה.
הפונקציה מתנהגת בדיוק אותו דבר, אבל על ממבר שונה.
ובגלל שאני לא מבצע היידינג לפונקציה, אני אצטרך שהפונקצייה המקורית תדע להתייחס לממבר הנכון. כלומר, אם אני במחלקה הנגזרת, אני רוצה שהפונקציה המקורית תבצע מה שצריך לפי הממבר שבמחלקה הנגזרת.

וזה מה ששאלתי אם זה אפשרי.
אני מקבל את ההרגשה שלא מבינים אותי, או שאני לא מבין את התשובה.
אז במילים פשוטות.

אם ההיידינג היחידי שאני מבצע, הוא היידינג של ממבר,
ואני מפעיל פונקציה כלשהיא ממחלקת הבסיס, שמשתמשת באותו ממבר.
באיזה ממבר תשתמש הפונקציה? במקורי או בחדש?


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ldan192 
חבר מתאריך 14.9.08
95119 הודעות
   00:54   08.06.10   
אל הפורום  
  23. עכשיו הבנתי מה אתה רוצה! קצת מוזר לי כי הבנתי ממך  
בתגובה להודעה מספר 22
 
שמדובר ב-2 מתודות שאחת ממיינת ואחת לא את אותו השדה,
אבל בכל מקרה, אני מאמין שקטע הקוד הבא שכתבתי יענה לשאלתך:

#include <iostream>
using namespace std;

class A {
public:
A(int y=1) : x(y) {}
int getx() {
return this->field();
}

private:
virtual int field() { return x; }
int x;
};

class B : public A {
public:
B(int y=3) : x(y) {}
private:
int field() { return x; }
int x;
};

int main() {
A a;
B b;
A &ab = reinterpret_cast<A&>(b);
cout << "A = " << a.getx() << ", B = " << b.getx();
cout << ", AB = " << ab.getx() << endl;
return 0;
}

נהוג יותר במקרים כאלה להשתמש בפונקציות חבר (ובגלל זה גם משתמשים לרוב באופרטורים כפונקציות חבר).
אבל נראה לי שהדוגמא שרשמתי תבהיר מספיק מה אתה צריך (להשתמש באופרטור במקום getx ובכל קריאה, במקום לקרוא ישירות לשדה - לפונקציה הוירטואלית המחזירה את השדה. בדומה ל-clone שהרבה פעמים ממשים).

בהצלחה ומקווה שהצלחתי לעזור בסוף


בברכה,
עידן


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Zippo 
חבר מתאריך 26.5.02
7921 הודעות
   05:13   11.06.10   
אל הפורום  
  24. אחלה! אני חושב שהבנתי.  
בתגובה להודעה מספר 23
 
יעבוד אחלה אם אני כותב את 2 הקלאסים.
ואם לא אני כותב את מחלקת הבסיס?
הרי אין לי פונקציה וירטואלית שמחזירה את את הממבר...
יש איזשהיא דרך שהפונקציה הישנה תשתמש ב- derived::x במקום ב- base::x?


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ldan192 
חבר מתאריך 14.9.08
95119 הודעות
   12:50   11.06.10   
אל הפורום  
  25. יש אפשרות עם templating :\ אפשר גם לבצע downcasting  
בתגובה להודעה מספר 24
 
ערכתי לאחרונה בתאריך 11.06.10 בשעה 12:58 בברכה, ldan192
 
נכפה ע"י הוספת פרמטר לפונקצייה, אבל על זה אצטרך לחשוב קצת איך כדאי לממש.

אז אני אחזור אליך מתישהו במהלך השבוע כשאתפנה יותר.


בברכה,
עידן


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Zippo 
חבר מתאריך 26.5.02
7921 הודעות
   14:51   11.06.10   
אל הפורום  
  26. לא לחוץ. טוב לידע כללי, אבל את התרגיל שבשבילו הייתי  
בתגובה להודעה מספר 25
 
צריך את זה, הגשתי מזמן


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ldan192 
חבר מתאריך 14.9.08
95119 הודעות
   17:35   11.06.10   
אל הפורום  
  27. כן, אני מתאר לעצמי. וחשבתי על זה קצת ולדעתי  
בתגובה להודעה מספר 26
 
יש כמה פתרונות:
1. לשמור מעין רשימה מקושרת של כתובות זכרון. רשימה אחת לכל טיפוס ולפי זה אתה יודע בהפעלת הפונקציות איך לבצע downcast (מהמתודה המוגדרת במחלקת הבסיס אלא זו ששלך) כשנדרש לפתרון הבעיה.

list_for_each(ptr, A_list) {
if (ptr == &this->node) success...
}

2. שימוש ב-typeid להוצאת הטיפוס הדינמי (לשים לב שלדינמי ולא לסטטי) וכך להפעיל את האופרטור המקורי רק עם ה-x שמתקבל מהטיפוס הדינמי.



using friend bool operator <(C *a1, C *a2);
שיורש משניהם

3. והכי מכוער, אי שימוש בירושה, הסתמכות על מבנה האיבר בזכרון, ואז לקרוא מאחד לשני.



class A {
public:
A(...)...
private:
int x;
}

class B {
public:
B(...)...
private:
int x;
}

int getx(void *d) { // void* just to magnify the idea
return reinterpret_cast<B*>(d)->x;
}

A a;
B b;
getx(&a); getx(&b);


אם תעלו עם עוד רעיונות אשמח לשמוע, אבל בסה"כ זה לא מפתיע שזו לא משימה פשוטה ב-++C כי בסה"כ זו שפה סטטית וברגע שלא משתמשים בכלי הכי בסיסי להפוכה לדינמאית - דיי הרסנו מהייחודיות שלה.


בברכה,
עידן


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד

תגובה מהירה  למכתב מספר: 
 
___________________________________________________________________

___________________________________________________________________
למנהלים:  נעל | תייק בארכיון | מחק | העבר לפורום אחר | מחק תגובות | עגן אשכול
       



© כל הזכויות שמורות ל-רוטר.נט בע"מ rotter.net