You are on page 1of 7

‫כללי‬

‫)‪ sizeof(static array‬נותן את גודל כל המערך בניגוד למערך דינאמי‪ ,‬שם יתקבל גודל המצביע‬

‫‪ Explicit‬לפני הבנאי‬
‫למניעת ‪implicit casting‬‬

‫מתי חייבים להשתמש בשורת האיתחול?‬


‫אובייקטים מוכלים שאין להם בנאי דיפולטי (כי הבנאי שלהם מופעל קודם)‬ ‫‪.1‬‬
‫משתנה קונסט‬ ‫‪.2‬‬
‫משתנה רפרנס (נדיר)‬ ‫‪.3‬‬

‫השילוש הקדוש של מחלקה עם הקצאה דינאמית‪:‬‬


‫מפרק‬ ‫‪.1‬‬
‫בנאי מעתיק‬ ‫‪.2‬‬
‫אופרטור השמה= (נשתמש בו בבנאי המעתיק)‬ ‫‪.3‬‬

‫העמסת אופרטורים – נקודות חשובות‬

‫אופרטור ההשמה‬
‫לא לשכוח לבדוק שהכתובות לא זהות‬
‫לא לשכוח לשחרר את התוכן הקיים אם בוצעה הקצאה דינאמית‬

‫האופרטור [ ]‪:‬‬
‫תקף גם למתודות המחזירות אובייקט שברצוננו לשנות‬
‫נעמיס פעמיים‪ ,‬פעם רגיל ופעם כקונסט‬
‫לדוגמא במחלקה ‪String‬‬
‫;)‪char& operator[](int index‬‬
‫;‪const char& operator[](int index) const‬‬
‫‪Consts & statics‬‬

‫אובייקט ‪:const‬‬
‫אסור לשנות באופן ישיר (לדוגמא השמה)‬ ‫‪.1‬‬
‫אסור להעביר אותו כפרמטר ‪ By Reference‬אלא אך ורק כ‪const -‬‬ ‫‪.2‬‬

‫אובייקט רגיל‪:‬‬
‫חשוב ללקוח לדעת באילו פונקציות האובייקט שלו מוגן‬

‫מתודה ‪:const‬‬
‫אסור לה לשנות שום שדה ‪ data‬של האובייקט המפעיל וגם לא לאפשר לו בעקיפין‬

‫כשמגדירים אובייקט קונסטי כגון (עמ' ‪ 76‬שורה ‪ )8‬וכגון (עמ' ‪ 78‬שורה ‪ )38‬אסור לאובייקט‬
‫להישתנות לעולם וזה כולל‪:‬‬
‫הקומפיילר לא יתן לו לעבור כפרמטר לפונקציה שלא מקבלת אותו כקונסט‬ ‫‪.1‬‬
‫הקומפיילר לא יתן לו להפעיל על עצמו מתודה שלא הוגדרה כקונסט‬ ‫‪.2‬‬
‫הערה‪ :‬אסור לעשות ‪ casting‬מקונסט ללא קונסט!‬

‫משתנים סטטיים‪:‬‬
‫משתנים סטטיים וגלובליים חיים כל התוכנית‬ ‫‪‬‬
‫משתנה סטטי מוכר רק בפונקציה שהוא כתוב בה‬ ‫‪‬‬
‫שדה סטטי יש אחד בכל ‪ class‬ולא אחד בכל אובייקט‬ ‫‪‬‬
‫חי תמיד‪ ,‬גם אם לא יצרנו בכלל אובייקטים‬ ‫‪‬‬
‫למשתנה סטטי יש ערך דיפולטי ‪0 -‬‬ ‫‪‬‬
‫גישה לשדה סטטי‪MyClass::MyField :‬‬
‫מתודה סטטית רשאית לגשת אך ורק לשדות סטטיים‬
‫מתודה רגילה יכולה לגשת גם לשדות רגילים וגם לשדות סטטיים‬

‫דוגמה להכרזה ואיתחול משתנה סטטי‪:‬‬


‫)‪static int counter; (H‬‬
‫)‪int className::counter = 0; (CPP‬‬

‫הערות‪:‬‬
‫מותר להגדיר ‪ class‬בתוך ‪ .class‬שם הפנימי יהיה ‪OutterClass::InnerClass‬‬ ‫‪.1‬‬
‫‪ – Enum‬שילוב של סטטי וקונסט‬ ‫‪.2‬‬
‫הורשה ופולימורפיזם‬
‫הערות כלליות‪:‬‬
‫הרשאת ‪ friend‬לא עוברת בהורשה‪.‬‬ ‫‪.1‬‬
‫לא יכול להתבצע זיהוי הקלאס בזמן ריצה אם אין טבלה וירטואלית!‬ ‫‪.2‬‬

‫תהליך יצירת אובייקט של מחלקה נורשת (ההריסה בסדר הפוך)‬


‫הפעלת הבנאי של מחלקת הבסיס‬ ‫‪.1‬‬
‫יצירת השדות של המחלקה הנורשת‬ ‫‪.2‬‬
‫אם יש שדות שהם אובייקטים מוכלים – הפעלת הבנאי שלהם‬ ‫‪.3‬‬
‫כניסה לגוף הבנאי של הנורשת‬ ‫‪.4‬‬

‫התנהגות השמה והעתקה בין אבא לבן‬


‫;‪Derived son‬‬
‫‪Base father = son; // OK, casting from Derived to Base and then Base copy c'tor‬‬
‫‪father = son; // OK, casting from Derived to Base, we lose information‬‬
‫‪Derived son2 = father; // not possible without appropriate copy c'tor‬‬
‫‪son2 = father ;// not possible without appropriate copy c'tor or = operator‬‬

‫שיטה וירטואלית – שיטה שה‪ binding -‬אליה הוא דינאמי (בזמן ריצה)‬
‫מחלקה פולימורפית – מחלקה שהשיטות בה וירטואליות‬
‫חשוב ‪ -‬כל פעם שנגדיר מחלקה כזאת נבנה עבורה מפרק וירטואלי‬
‫הסיבה – יתכן ובבנים שלה יש הקצאות דינאמיות שצריך לשחרר במפרק‬
‫אם יש לנו מצביע לאובייקט אב והוא מצביע על הבן ולאב אין מפרק וירטואלי‪ ,‬לא יופעל המפרק של‬
‫הבן‪.‬‬

‫שיטות וירטואליות – חוקים חשובים‬

‫השיטה תישאר וירטואלית גם במחלקות היורשות‪ ,‬אך לא חובה לציין זאת‬ ‫‪.1‬‬
‫את המילה "וירטואל" נכתוב רק בקובץ ‪H‬‬
‫בהפעלת פונקציה וירטואלית בבנאי של מחלקת בסיס תופעל הפונקציה של הבסיס אפילו‬ ‫‪.2‬‬
‫אם האובייקט הנוצר הוא יורש (כי עדיין לא הגענו לבנאי שלו!)‬
‫בהפעלת פונקציה וירטואלית במפרק של מחלקת הבסיס תופעל הפונקציה של הבסיס כי‬ ‫‪.3‬‬
‫כבר עברנו במפרק של היורש!‬
‫מוסיפות לאובייקט פוינטר לטבלה וירטואלית (נפח האובייקט גדל)‬ ‫‪.4‬‬
‫ללא טבלה וירטואלית יהיה קישור סטטי בלבד‬ ‫‪.5‬‬
‫מחלקות ושיטות אבסטרקטיות‬

‫מחלקה היא אבסטרקטית אם לפחות שיטה אחת היא אבסטרקטית‬


‫‪;virtual void doSomething() const = 0‬‬
‫עובדות על מחלקה אבסטרקטית‪:‬‬
‫אי אפשר לייצר ממנה אובייקט (נועדה שיירשו ממנה)‬ ‫‪.1‬‬
‫אי אפשר להעביר אותה ‪by value‬‬ ‫‪.2‬‬
‫אי אפשר להחזיר אותה ‪by value‬‬ ‫‪.3‬‬
‫ניתן להחזיק מצביע אליה או רפרנס אליה‬ ‫‪.4‬‬
‫כדי שמחלקה שיורשת ממנה לא תהיה אבסטרקטית היא צריכה לממש את כל השיטות‬ ‫‪.5‬‬
‫האבסטרקטיות‪)pure virtual( .‬‬
‫שיטה וירטואלית טהורה – אי אפשר להשתמש בה אלא רק בדריסות שלה‬ ‫‪.6‬‬

‫הורשה רוחבית מרובה‬


‫אם ילד יורש משני אבות בעלי אותה שיטה ולא דורס אותה‪ ,‬הסינטקס הוא‬
‫;)(‪son.father1::method‬‬
‫;)(‪son.father2::method‬‬

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

‫חוק‪ :‬סבא וירטואלי נולד לפני סבא לא וירטואלי‬

‫‪Dynamic-cast‬‬

‫ברצוננו לבדוק חלודה אך ורק לסירה ולצאצאים שלה‬


‫)‪Vehicle* v = new Boat(….‬‬
‫)‪;Boat* p = dynamic_cast<Boat*>(v‬‬
‫)‪If(p != NULL‬‬
‫‪p-‬‬
‫‪;)(>check_rust‬‬
‫‪Template‬‬

‫חוקים‪:‬‬
‫ביצירת אובייקט ממחלקה טמפלט יש לשלוח פרמטר לטמפלט לדוגמה ‪>Array<int‬‬ ‫‪.1‬‬
‫בקריאה לפונקציה טמפלט אין לציין את סוג הפרמטר‪ ,‬הפונקציה מזהה אותו‪.‬‬ ‫‪.2‬‬
‫במימוש ‪ member function‬מחוץ למחלקה טמפלט צריך לאזכר מחדש את השימוש‬ ‫‪.3‬‬
‫בטמפלט‬
‫כל המימושים בקובץ ‪H‬‬ ‫‪.4‬‬
‫הורשה‪ :‬המחלקה היורשת יכולה להישאר טמפלט אם נציין בראשה‬ ‫‪.5‬‬
‫>‪template<class T‬‬
‫>‪class derived: public base<T‬‬
‫או לא להיות טמפלט‪ ,‬אם נציין למשל‬
‫>‪Class derived: public base<int‬‬
‫‪ T‬ידוע בזמן קומפילציה‬ ‫‪.6‬‬

‫‪STL‬‬

‫כשנבנה מחלקה טמפלטית לקונטיינר מסויים‬


‫נבנה עבורה גם מחלקת איטרטור‪.‬‬
‫במחלקה הטמפלטית יהיו בין היתר השיטות‬
‫‪ -begin‬תחזיר איטרטור לתחילת המבנה‬ ‫‪.1‬‬
‫‪ -end‬תחזיר איטרטור לכתובת שאחרי ה"תא" האחרון במבנה הנתונים‬ ‫‪.2‬‬

‫מימוש איטרטור‬
‫נממש כ ‪ inner class‬במחלקה המייצגת את מבנה הנתונים‬
‫יתן הרשאת ‪ friend‬למחלקה של מבנה הנתונים אליו "שייך"‬
‫מחלקה שנעמיס בה‪:‬‬
‫* (ידמה גישה לתוכן מצביע)‬ ‫‪.1‬‬
‫‪(++‬ידמה קידום המצביע לתא הבא במבנה הנתונים תמיד משמאל)‬ ‫‪.2‬‬
‫=! (כדי להשוות בין איטרטורים)‬ ‫‪.3‬‬
‫==‬ ‫‪.4‬‬
‫‪ casting‬ל *‪T‬‬ ‫‪.5‬‬
‫שימוש באיטרטור‬
‫דוגמה ליצירת איטרטור על וקטור‬ ‫‪.1‬‬
‫;‪vector<T> myVector‬‬
‫;)(‪vector<T>::iterator iter = myVector.begin‬‬

‫וקטור‬
‫בניגוד למערך‪ ,‬ניתן להגדיר וקטור של אובייקטים גם אם אין להם בנאי דיפולט‬ ‫‪.1‬‬

‫‪Object function‬‬

‫מכיוון שלא ניתן לשלוח פונקציה טמפלטית כ"פעולה" שאנו רוצים לבצע על מבנה הנתונים‬
‫נעטוף אותה באובייקט‪ ,‬עליו נעמיס רק אופרטור ()‬

‫חשוב‪:‬‬
‫כשנשלח מצביע לפונקציה נכתוב בלי סוגריים‬
‫כשנשלח אובייקט נכתוב עם סוגריים!‬

‫דוגמה למימוש‪:‬‬
‫‪struct Print‬‬
‫{‬
‫>‪template<class T‬‬
‫‪void operator()(const T& printable) const‬‬
‫{‬
‫;‪cout << printable << endl‬‬
‫}‬
‫;}‬

‫קבצים‬

‫לעבודה עם קבצים צריך לכלול את ספריית ‪fstream‬‬


‫סינטקס‪:‬‬
‫‪ofstream outFile("name", flags) //write‬‬
‫‪ifstream inFile("name", flags) // read‬‬
‫‪fstream inOutFile("name", ios::in|ios::out|…..) //read&write‬‬
‫‪outFile.close(); // closing the first file‬‬

‫‪flags‬‬
‫‪ – ios::app‬הוספה לסוף הקובץ‪ ,‬נתונים קיימים לא ידרסו‬ ‫‪.1‬‬
‫‪ – ios::nocreate‬דרישה שהקובץ יהיה קיים והפקודה לא תיצור אותו‬ ‫‪.2‬‬
‫‪ – ios::noreplace‬דרישה שהקובץ לא יהיה קיים והפקודה תיצור אותו‬ ‫‪.3‬‬
‫‪ – ios::trunk‬פתיחת קובץ ריק‪ ,‬קובץ בשם זהה ימחק‬ ‫‪.4‬‬
‫‪( ios::binary‬הדיפולט הוא קובץ טקסט)‬ ‫‪.5‬‬

‫קובץ טקסט‬
‫אובייקט יכתב לקובץ שדה שדה‪ ,‬ניתן בעזרת האופרטור >>‬ ‫‪.1‬‬
‫ניתן לקרוא מהקובץ בעזרת האופרטור <<‪get, getline ,‬‬ ‫‪.2‬‬
‫כדי לבדוק אם הגענו לסוף נשתמש ב ‪)(eof‬‬ ‫‪.3‬‬

‫קובץ בינארי‬
‫ניתן לכתוב את האובייקט כיחידה אחת לקובץ אם אין מצביעים‬ ‫‪.1‬‬
‫נכתוב שיטת ‪ save‬במחלקות של אובייקטים שנרצה לשמור ונכתוב להן בנאי שמקבל קובץ‬ ‫‪.2‬‬
‫פתוח לקריאה (אם אנו קוראים מקובץ)‬
‫נעשה שימוש בפונקציות ‪read, write‬‬ ‫‪.3‬‬
‫בכתיבה נעשה המרה ל ‪*const char‬‬ ‫‪.4‬‬
‫בקריאה נעשה המרה ל ‪*char‬‬ ‫‪.5‬‬

You might also like