m13_casts - ‫המרות ב ++‪C‬‬ ‫2‬...

Info iconThis preview shows page 1. Sign up to view the full content.

View Full Document Right Arrow Icon
This is the end of the preview. Sign up to access the rest of the document.

Unformatted text preview: ‫המרות ב ++‪C‬‬ ‫2‬ ‫המרות (‪ )cast‬ב ++‪C‬‬ ‫• ב ++‪ C‬יש התייחסות ספציפית יותר להמרות (‪ )casting‬מאשר ב‬ ‫‪ .C‬ההמרה ב ‪ C‬היא "גסה" ויכולה להמיר כמעט כל דבר לכל‬ ‫דבר. ב ++‪ C‬יש ‪-cast‬ים מיוחדים למטרות שונות.‬ ‫• למרות שהמרות בסגנון ‪ C‬עדין תקפות ב ++‪ , C‬נעדיף המרות‬ ‫בסגנון ++‪ C‬כי‬ ‫– הן מבצעות יותר בדיקות של טיפוסים ומותאמות טוב יותר‬ ‫למטרותיהן הספציפיות‬ ‫– בולטות יותר בקוד‬ 3 C++ ‫הסינטקס של המרות ב‬ ‫הביטוי המומר‬ ‫הטיפוס אליו‬ ‫ממירים‬ ‫ מהצורה‬C ‫המרה ב‬ (type) expression :‫ בביטוי הבא‬C++ ‫תוחלף ב‬ castType<type>(expression) ...‫ יהיה אחד מ‬castType int a=1; double b = (double) a; :‫דוגמה‬ static_cast dynamic_cast const_cast b = static_cast<double>(a); reinterpret_cast • • • • ‫4‬ ‫‪static_cast‬‬ ‫דומה ל ‪ cast‬הכללי של ‪ .C‬פועל בזמן הידור.‬ ‫מתאים לביצוע המרות מפורשות הנתמכות בשפה (כמו בין ‪ int‬ל‬ ‫‪)double‬‬ ‫מתאים לביצוע המרות מפורשות הנתמכות ב ‪ constructors‬או‬ ‫אופרטורי המרה שהוגדרו במחלקות.‬ ‫מתאים לביצוע המרה במורד עץ הורשה (‪ ,)downcast‬כלומר‬ ‫ממחלקת בסיס למחלקה נגזרת. אם כי ‪ dynamic_cast‬יותר מתאים‬ ‫למטרה זו.‬ ‫לא יבצע דברים שלא נתמכים בצורה זו או אחרת, כמו:‬ ‫– המרה מפוינטר לטיפוס רגיל או אובייקט רגיל‬ ‫– המרה מפויטר מטיפוס אחד לפוינטר מטיפוס אחר‬ ‫– המרה בין אובייקטים שלא הוגדרה ב ‪ ctor‬או באופרטור‬ ‫– המרה מאובייקט ‪ const‬לאובייקט שאינו ‪const‬‬ ‫•‬ ‫•‬ ‫•‬ ‫•‬ ‫•‬ ‫5‬ ‫‪dynamic_cast‬‬ ‫נועד להמיר מפוינטר או רפרנס למחלקת בסיס‬ ‫לפוינטר (או רפרנס) למחלקה נגזרת.‬ ‫פועל בזמן ריצה.‬ ‫היתרון על-פני ‪ :static_cast‬מתבצעת בדיקה בזמן‬ ‫ריצה של חוקיות ההמרה, ואופרטור ה ‪ cast‬מעביר‬ ‫הודעה על אי-חוקיות.‬ ‫דוגמה:‬ ‫)‪f(Employee* pe‬‬ ‫;)‪Manager *pm = static_cast< Manager *>(pe‬‬ ‫... //‬ ‫•‬ ‫•‬ ‫•‬ ‫‪void‬‬ ‫{‬ ‫}‬ ‫•‬ ‫הפונקציה תעבור הידור, אך אם יישלח אליה ארגומנט‬ ‫שהטיפוס שלו בזמן ריצה לא מתאים, תהיה שגיאת ריצה.‬ ‫6‬ ‫‪dynamic_cast‬‬ ‫• הדרך הנכונה לכתוב את הפונקציה היא תוך שימוש ב‬ ‫‪:dynamic_cast‬‬ ‫{)++‪for (i=0; i<len; i‬‬ ‫{)‪for(j=0; j<len; ++j‬‬ ‫))]‪if( (Manager* temp = dynamic_cast<Manager*>(Dept[i‬‬ ‫)]‪&& temp-> is_manager_of(Dept[j‬‬ ‫} ‪{ // do something‬‬ ‫}‬ ‫}‬ ‫• אם ‪ dynamic_cast‬נכשל על פוינטר, מוחזר ‪.NULL‬‬ ‫• אם ‪ dynamic_cast‬נכשל על רפרנס, נזרק ‪ exception‬מטיפוס‬ ‫‪.std::bad_cast‬‬ ‫• ניתן להפעיל ‪ dynamid_cast‬רק על פוינטרים (או רפרנסים) של‬ ‫מחלקות שיש להן לפחות פונקציה וירטואלית אחת (אחרת מקבלים‬ ‫שגיאת הידור)‬ ‫7‬ ‫‪const_cast‬‬ ‫מיועד להסרת ה ‪ const‬מאובייקט. זהו ה ‪ cast‬היחיד שיכול‬ ‫להסיר ‪ constמאובייקט.‬ ‫לכאורה לא נחוץ, כיוון שאובייקט ‪ const‬אמור להישאר ‪const‬‬ ‫משמש בעיקר להעברת ארגומנט ‪ const‬לפונקציה שמקבלת‬ ‫פרמטר שאינו ‪( .const‬פונקציה שלא ניתן לשנות, למשל, אם‬ ‫היא נכתבה ע"י גורם אחר).‬ ‫;}...{‪class B‬‬ ‫דוגמה:‬ ‫)‪void g(B* pb‬‬ ‫} /*... */ {‬ ‫)‪void f(const B& x‬‬ ‫{‬ ‫... //‬ ‫;)‪g(const_cast<B*> &x‬‬ ‫...//‬ ‫}‬ ‫•‬ ‫•‬ ‫•‬ ‫•‬ ‫8‬ ‫‪reinterpret_cast‬‬ ‫משמש לביצוע המרות שאינן מוגדרות במפורש (ולכן לא ניתן‬ ‫לבצע אותן באמצעות ‪:)static_cast‬‬ ‫– המרות בין פוינטרים של טיפוסים שאין ביניהם קשר‬ ‫הורשה‬ ‫– המרות מפוינטר כלשהו ל ‪ int‬או מ ‪ int‬לפוינטר מסויים‬ ‫– דוגמה: שמירה של משתנה ‪ int‬לקובץ בצורה לא‬ ‫מפורמטת, וקריאה מתוך הקובץ:‬ ‫;)”‪ofstream outFile(“my_file‬‬ ‫;‪int a‬‬ ‫... //‬ ‫;))‪outFile.write(reinterpret_cast<char*>(&a), sizeof(a‬‬ ‫;)”‪ifstream inFile(“my_file‬‬ ‫;‪int b‬‬ ‫... //‬ ‫;))‪inFile.read(reinterpret_cast<char*>(&b), sizeof(b‬‬ ‫•‬ ...
View Full Document

Ask a homework question - tutors are online