פורסם 2009 ביוני 1616 שנים היי, קיבלתי מטלה בנושא פולימורפיזם בשיעורי הבית ואני מתלבט ביישום של אחת הפונקציות הנדרשות.בקצרה, הסיפור הוא כזה:יש מפעל שמייצר כלי מטבח (כוסות, צלחות, מזלגות וכו') ומכונה שממיינת את כל המוצרים. בתחילת כל יום מזינים למכונה את המוצרים שהמפעל מתכוון לייצר באותו יום (האובייקטים האלו מאוחסנים בוקטור) ולאחר מכן המכונה צריכה לבדוק כל מוצר שמגיע אליה ולהחליט האם הוא תקין - היא עושה זאת על ידי השוואתו לאובייקטים שנמצאים בוקטור שהזכרתי מקודם.יצויין גם כי כל הכלים במפעל יורשים מאובייקט משותף בשם Dish.הפרמטר הראשון והחשוב ביותר בהשוואה הוא לבדוק האם הם בכלל מאותו טיפוס (כלומר אם הגיע למכונה מזלג, והמפעל אמור לייצר היום רק צלחות, המוצר הזה אמור לעוף ישר לקופסא של מוצרים פגומים, שזה גם וקטור חסר חשיבות כלשהו).עכשיו, אני מכיר שתי דרכים לעשות את זה:א) להוסיף לאבא שדה של שם (סטרינג פשוט) שיאותחל על ידי כל אחד מהבנים באופן שונה. עבור כל אובייקט שיגיע למכונה, לעשות השוואה של השדה הזה מול כל אחד מהאובייקטים בוקטור.ב) לממש אופרטור השוואה בכל אחד מהבנים על ידי שימוש ב-dynamic_cast מתאים.הבעיה היא שהאפשרות הראשונה נחשבת על ידי סגל הקורס כ"התחכמות" וייתכן שיורידו על זה נקודות (למה להשתמש בפתרון הלוגי הפשוט ביותר אם אפשר לסבך הכל?) והאפשרות השניה דורשת הרצת dynamic_cast על כל תא בוקטור - ואם בשלב כלשהו יהיו לי הרבה מאוד תאים, זה לא הפתרון המועדף בשפת המעטה.יש דרכים נוספות בהן אפשר להשוות בין טיפוסים בזמן ריצה? :-\
פורסם 2009 ביוני 1616 שנים שתי הדרכים קצת הורסות את כל הקטע של פולימורפיזם. זו שאלה די טיפשית.הפתרון הפשוט ביותר הוא בדיוק פתרון א' שהצעת (רק שהייתי משתמש ב-Enum ולא במחרוזת). למעשה, אם אין הבדל "התנהגותי" בין המוצרים השונים, בכלל הייתי זורק לפח את הרעיון של ירושה ופשוט מממש את הכל במחלקה אחת (עם שדה שקובע את סוג המוצר).
פורסם 2009 ביוני 1616 שנים מחבר אתה כזה חמוד כשאתה נאיבי ;D לצערי יש כל מני מגבלות על התרגיל :-\ב-enum אני לא יכול להשתמש כי זה הורס עוד יותר את הגנריות של הקוד (שכבר ככה די נהרסת אם אני מכניס בעצמי סטרינג של שם לכל בן) - יכול להיות שבעתיד יהיו עוד 50 מוצרים שונים שמישהו אחר יממש ויותר פשוט לדרוש ממנו להוסיף סטרינג של שם לקונסטרקטור מאשר להסתבך עם enum שלא תהיה לו גישה אליו בכלל.ולצערי אי אפשר לזנוח את רעיון הירושה בגלל מגבלות התרגיל.. לכל כלי יש פרמטרים שונים במקצת (לצלחות וכוסות יש רדיוס וגובה, למזלגות יש אורך)... ברור שאפשר לממש את הכל במחלקה אחת, אבל אני חייב ליצור לפחות שלוש מחלקות שיורשות מהאב הראשי (ועוד מעין מחלקת ביניים).
פורסם 2009 ביוני 1616 שנים אז אין באמת דרך אחרת.גם בשפות אחרות (ג'אווה, #C) משתמשים בבדיקה של טיפוסים בזמן ריצה.
פורסם 2009 ביוני 1616 שנים מחבר איך עושים את זה בשפות אחרות? אין איזו פונקציה פשוטה שיכולה לעשות את זה? :\
פורסם 2009 ביוני 1616 שנים בג'אווה וב-#C פשוט יש keywords מתאימים לזה (instanceof ו-is).ב-++C יש לך שתי אפשרויות:http://en.wikipedia.org/wiki/Run-time_type_informationhttp://en.wikipedia.org/wiki/Typeid
פורסם 2009 ביוני 1616 שנים מחבר אז אני יכול בעצם להשתמש ב-typeid, לא?חוץ מזה שלא ממש הבנתי מה היא מחזירה..
פורסם 2009 ביוני 1616 שנים אובייקט מטיפוס type_info.הפתרון הזה דווקא נראה לי פחות טוב, כי אי אפשר לבדוק אם הטיפוס של האובייקט שלך יורש מטיפוס אחר (אפשר רק להשוות).אגב, יש דרך קצת יותר יפה לעשות את פתרון א':להגדיר ל-Dish פונקציה וירטואלית טהורה בשם getType שמחזירה String. כל אחד מסוגי המוצרים השונים יממש את getType בהתאם.
פורסם 2009 ביוני 1616 שנים מחבר אגב, יש דרך קצת יותר יפה לעשות את פתרון א': להגדיר ל-Dish פונקציה וירטואלית טהורה בשם getType שמחזירה String. כל אחד מסוגי המוצרים השונים יממש את getType בהתאם. עוד מישהו הציע לי את זה, נראה לי שזה באמת הפתרון שאני אלך עליו. תודה רבה!
פורסם 2009 ביוני 1616 שנים אובייקט מטיפוס type_info.הפתרון הזה דווקא נראה לי פחות טוב, כי אי אפשר לבדוק אם הטיפוס של האובייקט שלך יורש מטיפוס אחר (אפשר רק להשוות).אגב, יש דרך קצת יותר יפה לעשות את פתרון א':להגדיר ל-Dish פונקציה וירטואלית טהורה בשם getType שמחזירה String. כל אחד מסוגי המוצרים השונים יממש את getType בהתאם.סתם מתוך סקרנות, איך הפתרון הזה יותר טוב? זה פחות או יותר מה שהאופרטור typeid עושה. ואיך הוא בדיוק פותר לך את הבעייה?
פורסם 2009 ביוני 1616 שנים אני גם בעד פתרון הסטרינג, אבל אם אתה רוצה משהו אחר תוכל לעשות double dispatchhttp://en.wikipedia.org/wiki/Double_dispatch
פורסם 2009 ביוני 1816 שנים ואם רוצים בכל זאת לעשות עם ה DYNAMIC CAST איך אני יכול לבדוק איבר בוקטור אם הוא מאותו טיפוס של האיבר שאותו אני רוצה לבדוק?כאמור, אסור לציין את הטיפוס הנידרש בתוך הקוד של המכונה הבודקת, זאת אומרת אני לא יכול לרשום בקוד המכונה בדיקה בסגנון הבא: TYPE* dynamic_cast<TYPE*> (object);אם האיבר מתאים אני אמור להכניס אותו למקום המתאים בוקטור שמכילים איברים מהסוג שלו ולכן חשבתי לעבור בלולאה על האיברים בוקטורים וברגע שיש התאמה בין האיבר הניבדק לבין האיבר בוקטור, אז להכניס אותו לאותו המקום.
פורסם 2009 ביוני 1816 שנים כמו שאמרנו כאן, יש לך שתי אפשרויות:הראשונה היא להוסיף פריט מזהה לקלאס שלך (כמו פונקציית getType).השנייה היא להשתמש בבדיקת טיפוסים בזמן ריצה.את הדרך השנייה אפשר לממש באמצעות dynamic_cast או באמצעות typeid.אגב, אם אתה לא רוצה להשתמש ב-typeid אתה יכול לעשות משהו כזה:class Dish { virtual bool isSameType(Dish*) = 0;}ואז בכל קלאס שמממש את Dish לעשות משהו כזה:class Plate : public Dish { virtual bool isSameType(Dish* d) { Plate* p = dynamic_cast<Plate*>(d); return (p != null); }}כמובן שאת המימוש הזה תצטרך לעשות לכל טיפוס שיורש מ-Dish. אופציה קצת יותר חסכונית היא לשלב ירושה ו-Templates.יש גם את האופציה של double dispatch שהוצעה מעליי, אבל אני לא בטוח שהיא ישימה במקרה הזה (ואם כן, אז זה פתרון מאוד מסורבל).
פורסם 2009 ביוני 1816 שנים ואז אני יכול למעשה לעשות לולאה כזאת?for ( BoxIterator iterator = m_dishBoxes.begin(); iterator != m_dishBoxes.end(); iterator++ ) { if ( iterator->isSameType( dish ) ) { iterator->pushback(dish); break; } } תודה על ההסבר.
פורסם 2009 ביוני 1816 שנים מה הטיפוס של m_dishBoxes? אם זה וקטור של וקטורים, אז אתה לא יכול, כי לוקטור אין פונקציה בשם isSameType.
ארכיון
דיון זה הועבר לארכיון ולא ניתן להוסיף בו תגובות חדשות.