עבור לתוכן

בדיקת טיפוסים בזמן ריצה ב-C++

Featured Replies

פורסם

m_dishBoxes זה אכן וקטורים של וקטורים.

ואם אני אעשה את הקוד כך זה אמור להיות בסדר? (אני לא יודע אם הסינטקס עובד ככה)

for ( int generalCounter=0, innercouner=1; counter <= m_dishBoxes.size(); counter++ )
{

if ( (m_dishBoxes[generalCounter][innercouner])->isSameType( dish ) )
{
m_dishBoxes[generalCounter]->pushback(dish);
break;
}

}

  • תגובות 45
  • צפיות 6.1k
  • נוצר
  • תגובה אחרונה
פורסם

איפה אתה מקדם את generalCounter?

חוץ מזה, מה עם אחד מהוקטורים שב-m_dishBoxes ריק? זה יגרום לשגיאה.

אתה חייב לשמור איפשהו אובייקט אחד מכל טיפוס שיורש מ-Dish (זה יהיה אובייקט "dummy", כלומר לא איכפת לך ממה שהוא מכיל, אלא רק מהטיפוס שלו).

פורסם

זה הקוד המעודכן שחשבתי עליו, האם לדעתך הוא מתאים ומכסה את הבעיות שציינת?

if ( m_dishBoxes.empty() )
{
m_dishBoxes[1].pushback(dish);
}
else
{
for ( int generalCounter=0, innercounter=1; generalCounter <= m_dishBoxes.size(); generalCounter++ )
{

if ( (m_dishBoxes[generalCounter][innercounter])->isSameType( dish ) )
{
m_dishBoxes[generalCounter]->pushback(dish);
break;
}
else
{
m_dishBoxes[generalCounter+1]->pushback(dish);
break;
}

{
}

פורסם

יש פה המון סתירות. אתה מתבלבל בין הוקטור m_dishBoxes לבין הוקטורים שהוא מכיל.

לדוגמה, ה-if הראשון בודק אם הוקטור m_dishBoxes ריק. אם הוא ריק, אז אתה לא יכול לגשת אליו בכלל (כלומר [m_dishBoxes[1 חורג מהגבולות שלו).

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

פורסם
  • מחבר

זה לא יעבוד, ה-else שלך מנסה לדחוף פוינטר לאובייקט לתוך וקטור שלא בטוח שקיים בכלל (generalCounter+1 - מאיפה לך שיש שם תא בכלל?).

מה גם שהבדיקה של הכלי צריכה להיות מול וקטור CorrectDishes ולא מול m_dishBoxes...

פורסם

הבנתי אתכם.

אז איך אני אמור לשבץ נכון את האובייקטים?

(אני לא הבנתי את ההצעה עם האובייקטים :-\ DUMMIES ).

פורסם

נראה לי שצריך עוד קצת מידע (מה זה CorrectDishes שמינימייזר דיבר עליו?)

פורסם

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

minimizer רשם "מה גם שהבדיקה של הכלי צריכה להיות מול וקטור CorrectDishes ולא מול m_dishBoxes..."

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

פורסם
  • מחבר

שניצל, זה חלק מתרגיל הבית (שמשותף לשנינו מסתבר :)).

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

אם הוא תואם במדויק לאחד מהם, אזי צריך לשים אותו בתוך וקטור נפרד - ואת הוקטור הנפרד הזה לדחוף לתוך הוקטור של dishBoxes.

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

אם מגיעה צלחת כחולה, אז היא לא מתאימה ודוחפים אותה לוקטור אחר של InvalidDishes.

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

פורסם

אבל איך תדע איזה וקטור ב-dishBoxes מתאים לאיזה כלי ב-CorrectDishes?

פורסם

זה למה רשמתי את השורה הזאת:

 m_dishBoxes[generalCounter][innercounter])->isSameType( dish )

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

פורסם

רעיון יותר טוב:

תאתחל את m_dishBoxes שיכיל וקטורים ריקים, כמספר האיברים ב-CorrectDishes.

ככה לכל איבר ב-CorrectDishes יהיה וקטור מקביל ב-m_dishBoxes.

פורסם
  • מחבר

אבל איך תדע איזה וקטור ב-dishBoxes מתאים לאיזה כלי ב-CorrectDishes?

כאמור עוד לא הגעתי לשלב היישום :P

הרעיון שלך יכול לעבוד, אני אנסה אותו מחר כנראה... ^_^

פורסם

אממ מעניין אנסה לעשות זאת.

תודה על העזרה.

פורסם

חשבתי להתערב פה קצת, ולהעיר עמה הערות כלליות על מה שכתבו כאן עד עכשיו, וכך לתרום את תרומתי לשלום העולם או לפחות לקוד נקי מבאגים:

1) בתוכנה גדולה ורצינית, עדיף להשתמש ב-RTTI המובנה בשפה ולא לכתוב אחד משלכם עם enum-ים. הקומפיילר יודע לעשות את זה מצויין, יעיל, ועם הרבה פחות באגים. בדיוק מאותה סיבה אתם משתמשים ב-virtual function וירושה במקום לממש בעצמכם function tables וירושה עם struct-ים.

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

2) ממה שהתרשמתי, התכנון (ואולי עצם הגדרת התרגיל) מגדירים מבנה תוכנה שנחשב היום גרוע ומעוות. יקח הרבה יותר זמן להסביר בדיוק למה אני מתכוון ולכן אני רק ארשום נקודות:

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

* נראה שהפתרון צועד לכיוון cosmic hierarchy, שיטה שבאמצע שנות התשעים התחילו להבין שב-C++ היא בעייתית. היא מעודדת דברים כמו heterogeneous containers ואינספור switch-ים ובדיקות טיפוסים, אשר גורמים לבאגים וקשיי תחזוקה. תלוי במשימה כמובן, אבל הרבה פעמים אפשר וכדאי לתכנן את היררכית האוביקטים ואת התוכנה אחרת.

3) חלק מהבעיות שאתם מנסים לפתור (לדוגמא operator==) נובעות מתכנון ההירכיה שלכם.

כמובן כמו כל ההמלצות, יש מצבים שבהם כמובן ההמלצות הנ"ל לא נכונות.

באמת קטונטי מלהסביר את כל זה ולכן אני אשלח את כולם לקרוא את Scott Meyers (הספרים הם ++effective c וכן ++more effective C). עוד כדאי לקרוא את herb sutter, ואת C++ report וכמובן לחפש את הנושאים באינטרטרון.

http://www.ddj.com/cpp/184401613

ארכיון

דיון זה הועבר לארכיון ולא ניתן להוסיף בו תגובות חדשות.

דיונים חדשים