PowerPoint Presentation

מסמכים קשורים
Slide 1

תכנות מונחה עצמים א' – תש"ע

Microsoft PowerPoint - rec1.ppt

Slide 1

מבוא למדעי המחשב

Slide 1

סדנת תכנות ב C/C++

מהוא לתכנות ב- JAVA מעבדה 3

מבוא למדעי המחשב

PowerPoint Presentation

Microsoft PowerPoint - rec3.ppt

PowerPoint Presentation

מבוא למדעי המחשב

Slide 1

תרגול 1

Slide 1

שאלהIgal : מערכים דו מימדיים רקורסיה:

PowerPoint Presentation

שאלהIgal : מערכים דו מימדיים רקורסיה:

Microsoft Word - דוגמאות ב

PowerPoint Presentation

מבוא לתכנות ב- JAVA תרגול 7

PowerPoint Presentation

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

מבוא למדעי המחשב

Microsoft PowerPoint - T-10.ppt [Compatibility Mode]

שאלהIgal : מערכים דו מימדיים רקורסיה:

פתרון מוצע לבחינת מה"ט ב_שפת c מועד ב אביב תשע"ט, אפריל 2019 מחברת: גב' זהבה לביא, מכללת אורט רחובות שאלה מספר 1 מוגדרת מחרוזת המורכבת מהספרות 0 עד 9.

יוםראשון, 02 ליולי 2014 סמסטר סוף מבחן )236703( עצמים מונחה תכנות - א' מועד 2014, אביב סמסטר קמחי יחיאל ד"ר מרצה: מסינג מיטל עבדאלקאדר, כרם גלעד, ערן

תרגול מס' 4: המתרגם שימוש במחלקות קיימות מחרוזות, קבצים, וקבלת קלט מהמשתמש

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

משימה תכנית המתרגמת קטעי טקסט לשפה אחרת הקלט: קובץ המכיל את קטעי הטקסט וכן את השפה אליה רוצים לתרגם תרגול מס' 4: המתרגם שימוש במחלקות קיימות תכנות מתק

מספר מחברת: עמוד 1 מתוך 11 ת"ז: תשע"א מועד ב סמסטר א' תאריך: 00:11 שעה: 0 שעות הבחינה: משך כל חומר עזר אסור בשימוש בחינה בקורס: מבוא למדעי ה

Slide 1

Microsoft Word - c_SimA_MoedB2005.doc

מבחן סוף סמסטר מועד ב 28/10/08 מרצה אחראית: דר שירלי הלוי גינסברג מתרגלים: גלעד קותיאל, גדי אלכסנדרוביץ הוראות: א. בטופס המבחן 6 עמודים (כולל דף זה) ו

הטכניון - מכון טכנולוגי לישראל

הגשה תוך שבוע בשעת התרגול

PowerPoint Presentation

אוניברסיטת חיפה החוג למדעי המחשב מרצה: שולי וינטנר מתרגלים: נעמה טוויטו, מחמוד שריף מבוא למדעי המחשב סמסטר א' תשע"ב בחינת סיום, מועד א', הנחי

Slide 1

Microsoft PowerPoint - rec8.ppt

Slide 1

תוכן העניינים

תרגול 1

PRESENTATION NAME

Microsoft Word B

אוניברסיטת חיפה החוג למדעי המחשב מרצה: שולי וינטנר מתרגלים: נעמה טוויטו, מחמוד שריף מבוא למדעי המחשב סמסטר א' תשע"ב בחינת סיום, מועד א', הנחי

Microsoft PowerPoint - lec2.ppt

יום שלישי, 14 ליולי 2015 מבחן סוף סמסטר - תכנות מונחה עצמים )236703( סמסטר אביב 2015, מועד א' מרצה: ערן גלעד מתרגלים: נורית מושקוביץ', הלאל עאסי, אליר

Microsoft PowerPoint - lec9.ppt

Slide 1

PowerPoint Presentation

מבוא לתכנות ב- JAVA תרגול 11

Slide 1

מבוא למדעי המחשב - חובלים

פתרון 2000 א. טבלת מעקב אחר ביצוע האלגוריתם הנתון עבור הערכים : פלט num = 37, sif = 7 r האם ספרת האחדות של sif שווה ל- num num 37 sif 7 שורה (1)-(2) (

מבוא למדעי המחשב - חובלים

מבחן 7002 פרטים כלליים מועד הבחינה: בכל זמן מספר השאלון: 1 משך הבחינה: 3 שעות חומר עזר בשימוש: הכל )ספרים ומחברות( המלצות: קרא המלצות לפני הבחינה ובדי

PowerPoint Presentation

תוכן העניינים

234114

ex1-bash

Microsoft PowerPoint - lec9.ppt

מבחן סוף סמסטר מועד א 15/02/08 מרצה אחראית: דר שירלי הלוי גינסברג מתרגלים: גלעד קותיאל, דניאל גנקין הוראות: א. בטופס המבחן 7 עמודים ו 4 דפי נוסחאות. ב

מספר זהות: סמסטר ב' מועד א' תאריך: 11102/4// שעה: 9:22 משך הבחינה: 3 שעות חומר עזר: אין מותר השימוש במחשבון פשוט בחינה בקורס: מבני נתונים מרצה: הדר בי

מערכות הפעלה

Slide 1

1 תבניות טקסט מהי תבנית טקסט? שימוש ב- Characters Meta שימוש ב- Expression Grouping שימוש ב- Quantifiers תת תבניות הפונקציה preg_match הפונקציה preg_m

אוניברסיטת חיפה החוג למדעי המחשב.5.6 מבוא למדעי המחשב סמסטר א' תשע"ז בחינה סופית מועד א', מרצה: שולי וינטנר מתרגלים: סמאח אידריס, ראמי עילבו

Tutorial 11

2013/14 אוניברסיטת חיפה מבוא למדעי מחשב, מעבדה מטרת המעבדה: לתרגל את המעבר מאלגוריתם לקוד C כמה שיותר. הוראות:.1.2 ניתן לעבוד ביחידים או בזוגות. (יש מ

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

שקופית 1

Microsoft Word - pitaron222Java_2007.doc

PowerPoint Presentation

הגשה תוך שבוע בשעת התרגול

מבוא למדעי המחשב

Microsoft PowerPoint - 10_threads.ppt

PowerPoint Presentation

Slide 1

לנץ קרן מרצה: תכנותמונחהעצמים) ( יוםשישי 15 אוקטובר 0202 ב מועד 0202, אביב סמסטר סמסטר סוף מבחן גוטמן אייל רביב, אריאל משנה, אלון מתרגלים: הנחי

תשע"דד אביב תוכנה 1 תרגיל מספר 4 עיבוד מחרוזות וקריאה מקבצים הנחיות כלליות: קראו בעיון את קובץ נהלי הגשת התרגילים אשר נמצא באתר הקורס..(

Microsoft PowerPoint - lec10.ppt

תרגיל 1 בקורס תוכנה 1

תורת הקומפילציה

PowerPoint Presentation

דוגמאות שהוצגו בהרצאה 10 בקורס יסודות מערכות פתוחות דוגמה 1 דוגמאות של פונקציות ב- awk שמראות שהעברת פרמטרים של משתנים פשוטים היא by value והעברת פרמט

PowerPoint Presentation

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

Microsoft Word - Ass1Bgu2019b_java docx

PowerPoint Presentation

úåëðä 1 - çæøä

מבוא לאסמבלי

PowerPoint Presentation

Slide 1

תמליל:

המחלקה String עבודה עם קבצים תבניות חריגות

שימוש בבנאים, הורסים והעמסת אופרטורים 2

השימוש במחלקות, בנאים, הורסים והעמסת אופרטורים מאפשר לנו להגדיר מחלקה עבור String כך שייחסכו מאיתנו החסרונות של השימוש ב-* char בזכות בנאים והורסים לא נצטרך לנהל את הזיכרון ידנית בזכות העמסת אופרטורים נוכל לשמור על כל הנוחות של,char* למשל גישה כמערך בזכות העמסת אופרטורים נוכל לאפשר פעולות בסיסיות בצורה נוחה - למשל שרשור 3

class String { int length; char* data; static char* allocate_and_copy(const char* data, int size); void verify_index(int index) const; public: String(const char* str = ""); // String s1; or String s1 = "aa"; String(const String& str); // String s2(s1); ~String(); int size() const; String& operator=(const String&); // s1 = s2; 4

String& operator+=(const String& str); // s1 += s2; const char& operator[](int index) const; // s[5] for const s char& operator[](int index); // s[5] for non-const s ; friend ostream& operator<<(ostream&, const String&); // cout << s1; friend bool operator==(const String&, const String&); // s1==s2 friend bool operator<(const String&, const String&); // s1<s2 bool operator!=(const String& str1, const String& str2); bool operator<=(const String& str1, const String& str2); bool operator>(const String& str1, const String& str2); bool operator>=(const String& str1, const String& str2); String operator+(const String& str1, const String& str2); 5

void error(const char* str) { cerr << "Error: " << str << endl; exit(0); בהמשך נחליף את error בשימוש בחריגות char* String::allocate_and_copy(const char* str, int size) { return strcpy(new char[size + 1], str); פונקצית עזר סטטית, אין לנו כאן צורך ב- this 6

String::String(const char* str) { length = strlen(str); data = allocate_and_copy(str, length); String::String(const String& str) : length(str.size()), data(allocate_and_copy(str.data, str.length)) { String::~String() { delete[] data; int String::size() const { return length; 7

String& String::operator=(const String& str) { if (this == &str) { return *this; delete[] data; data = allocate_and_copy(str.data, str.length); length = str.length; return *this; String& String::operator+=(const String& str) { char* new_data = allocate_and_copy(data, this->length + str.length); strcat(new_data, str.data); delete[] data; length += str.length; data = new_data; return *this; 8

void String::verify_index(int index) const { if (index >= size() index < 0) { error("bad index"); return; const char& String::operator[](int index) const { verify_index(index); return data[index]; פונקציות המחזירות & צריכות char& String::operator[](int index) { verify_index(index); return data[index]; בדרך כלל שתי גרסאות - עבור עצמים רגילים ועבור קבועים 9

bool operator==(const String& str1, const String& str2) { return strcmp(str1.data, str2.data) == 0; ostream& operator<<(ostream& os, const String& str) { return os << str.data; bool operator<(const String& str1, const String& str2) { return strcmp(str1.data, str2.data) < 0; 10

bool operator!=(const String& str1, const String& str2) { return!(str1 == str2); bool operator<=(const String& str1, const String& str2) { return!(str2 < str1); bool operator>(const String& str1, const String& str2) { return str2 < str1; bool operator>=(const String& str1, const String& str2) { return str2 <= str1; String operator+(const String& str1, const String& str2) { return String(str1) += str2; 11

int main(int argc, char **argv) { String s = "So long"; String s2 = "and thanks for all the fish."; String s3 = s + " " + s2; s3[s3.size() - 1] = '!'; cout << s3 << endl; return 0; כל האפשרויות הקיימות עבור char* נתמכות במחלקה החדשה, רק כעת אין צורך בניהול זיכרון מפורש 12

קובץ ה- header string מהספריה הסטנדרטית של ++C מכיל מימוש של המחלקה std::string אשר תומכת בכל הפעולות שמימשנו כאן ועוד הקפידו להשתמש ב- std::string ולא ב-* char עבור מחרוזות ב-++ C 13

ו- ifstream ofstream המחלקות 14

כמו ב- C גם ב-++ C הטיפול בקבצים דומה לטיפול בערוצי הקלט/פלט הסטנדרטיים ב-++ C עבודה עם קבצים מתבצעת בעזרת מחלקות המוגדרות בקובץ fstream המחלקה ofstream משמשת לכתיבה לקובץ המחלקה ifstream משמשת לקריאה מקובץ לשתי המחלקות יש בנאי המקבל את שם הקובץ לפתיחה לשתי המחלקות יש הורס המוודא שהקובץ נסגר כאשר העצם נהרס הדפסה וקריאה מתבצעות על ידי שימוש ב-<< ו->> כמו עבור ערוצים רגילים שאר הפעולות הדרושות על ערוצי הפלט מבוצעות כמתודות של המחלקות למשל המתודה eof מחזירה חיווי האם הגענו לסוף הקובץ 15

#include <fstream> using std::ifstream; using std::ofstream; using std::cerr; using std::endl; void copyfile(const char* fromname, const char* toname) { ifstream from(fromname); if (!from) {! )סימן קריאה( cerr << "cannot open file " << fromname << endl; return; ofstream to(toname); if (!to) { cerr << "cannot open file " << toname << endl; return; while (!from.eof()) { char c; from >> c; to << c; אופרטור למה לא צריך לסגור את הקובץ? 16

תבניות של פונקציות תבניות של מחלקות 17

נניח שברצוננו לכתוב פונקציה למציאת המקסימום במערך של עצמים לכל טיפוס נצטרך לרשום מחדש פונקציה כמעט זהה int max(const int* array, int size) { int result = array[0]; for (int i = 1; i < size; ++i) { if (result < array[i]) { result = array[i]; return result; string max(const string* array, int size) { string result = array[0]; for (int i = 1; i < size; ++i) { if (result < array[i]) { result = array[i]; return result; קל לנו לראות את התבנית הכללית של פונקציות המוצאות מקסימום במערך רק שם הטיפוס משתנה )בדוגמאות שלנו int ו- string ( ברצוננו לכתוב קוד גנרי שיתאים לכל טיפוס כיצד עשינו זאת ב- C? מה היו החסרונות בשיטה זו? 18

ניתן לכתוב תבניות של קוד - קוד התלוי בפרמטרים של זמן הקומפילציה כדי להגדיר תבנית לפונקציה משתמשים במילה השמורה template לפני הגדרת הפונקציה ומכריזים בתוך < > על הפרמטרים של התבנית: ניתן להשתמש במילה השמורה במקום ב- class typename בתוך קוד התבנית T מייצג שם של טיפוס וניתן להשתמש בו כמו בשם של טיפוס רגיל: להכריז על משתנים מסוג T ולבצע עליהם פעולות הקומפיילר ישתמש בתבנית כדי ליצור קוד במקרה הצורך תהליך יצירת מופע של הקוד המוגדר על ידי התבנית מתבצע בזמן הקומפילציה וקרוי instantiation תבניות יש להגדיר תמיד בקבצי template<class T> T max(const T* array, int size) { T result = array[0]; for (int i = 1; i < size; ++i) { if (result < array[i]) { result = array[i]; return result; h כך שיהיו זמינות לקומפיילר 19

כדי להשתמש בפונקציה המוגדרת על ידי תבנית ניתן לקרוא לה לפי שמה ובתוספת הפרמטרים הדרושים לתבנית: int array[] = {4, -1,2; string array2[] = {"Hello", "cruel", "world"; cout << max<int>(array, 3) << endl; cout << max<string>(array2, 3) << endl; ניתן לקרוא לפונקציה ללא ציון הפרמטרים לתבנית - במקרה זה הקומפיילר יסיק אותם בעצמו במקרה זה הפונקציה משתתפת בשלב פתרון ההעמסה יחד עם פונקציות נוספות int array[] = {4, -1,2; string array2[] = {"Hello", "cruel", "world"; cout << max(array, 3) << endl; cout << max(array2, 3) << endl; max<int> ולכן תיקרא int* הוא array max<string> ולכן תיקרא string* הוא array2 20

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

דוגמאות: int max(int a, int b, int c ) { if (a > b && a > c) return a ; if (b > c) return b ; return c; //... int j = max (1,3,3); // char c = max ('w','w','w');// String s = max (s1,s2,s3); // int j = max (1,'a','a'); // template<class T> T max (const T& a, const T& b, const T& c) { if (a > b && a > c) return a ; if (b > c) return b ; return c; //... int j = max(1,3,3); // char c = max ('w','w','w'); // String s = max (s1,s2,s3); // int j = max (1,'a','a'); // int j = max<int> (1,'a','a'); // קבועי תו ב- ++c הם מטיפוס char 22

כאשר הקומפיילר משתמש בתבנית הוא מנסה ליצור פונקציה לפי התבנית על ידי החלפת הפרמטרים לתבנית בערכים שהועברו לה. template<class T> T max(const T* array, int size) { T result = array[0]; for (int i = 1; i < size; ++i) { if (result < array[i]) { result = array[i]; return result; האם תהליך זה יכול להיכשל? Stack array[] = { Stack(50), Stack(60), Stack(70) ; cout << max(array, 3) << endl; בכדי שהשימוש בתבנית יצליח על הארגומנטים המועברים לתבנית לעמוד בדרישות הלא מפורשות על הטיפוס המופיעות בקוד אילו דרישות יש על הטיפוס T ב- max? 23

האם היינו יכולים לספק פונקציה דומה שתדרוש פחות מהטיפוס T? template<class T> int max_pos(const T* array, int size) { int max_id = 0; for (int i = 1; i < size; ++i) { if (array[max_id] < array[i]) { max_id = i; return i; הפונקציה הזו מציבה רק את הדרישה המינימלית האפשרית אופרטור > זאת בניגוד לפונקציה בשקף הקודם, שדורשת 4 מצד שני, פונקציית פעולות max() שמחזירה את האיבר עצמו יכולה להיות נוחה מאוד... במצבים כאלה ניתן לספק מספר פונקציות תבנית שונות המציבות דרישות שונות על הטיפוס, ולתת למשתמש לבחור את האופציה המתאימה לו 24

ניתן להגדיר תבנית עבור מחלקה ובכך לממש מחלקות גנריות בדומה ל- C בניגוד ל- C לא נצטרך לשלוח מצביעים לפונקציות והקומפיילר יוודא את נכונות הטיפוסים בעצמו template <class T> class Array { T* data; int size; public: explicit Array(int size); Array(const Array& a); ~Array(); Array& operator=(const Array& a); int size() const; T& operator[](int index); const T& operator[](int index) const; ; בתוך ההכרזה על המחלקה ניתן לרשום Array במקום Array<T> 25

בניגוד לפונקציות, עבור מחלקות חייבים לרשום במפורש את הארגומנטים לתבנית - הקומפיילר לא יכול להסיק אותם בעצמו כל שימוש בתבנית עם ארגומנטים אחרים יוצר טיפוס חדש void f(array<string>& words) { Array<int> numbers(100); for(int i = 0; i < numbers.size(); ++i) { numbers[i] = i; words = numbers; // error, type mismatch 26

template <class T> class Stack { T* data; int size; int nextindex; נשפר את המחסנית שלנו כך שתהיה גנרית: public: explicit Stack(int size = 100); Stack(const Stack& s); ~Stack(); Stack& operator=(const Stack&); void push(const T& t); void pop(); T& top(); const T& top() const; int getsize() const; ; 27

template <class T> Stack<T>::Stack(int size) : data(new T[size]), size(size), nextindex(0) { template <class T> Stack<T>::Stack(const Stack<T>& s) : data(new T[s.size]), size(s.size), nextindex(s.nextindex) { for (int i = 0; i < nextindex; ++i) { data[i] = s.data[i]; template <class T> Stack<T>::~Stack() { delete[] data; 28

template <class T> Stack<T>& Stack<T>::operator=(const Stack<T>& s) { if (this == &s) { return *this; delete[] data; data = new T[s.size]; size = s.size; nextindex = s.nextindex; for (int i = 0; i < nextindex; ++i) { data[i] = s.data[i]; return *this; 29

template <class T> void Stack<T>::push(const T& t) { if (nextindex >= size) { error("stack full"); data[nextindex++] = t; template <class T> void Stack<T>::pop() { if (nextindex <= 0) { error("stack empty"); nextindex--; 30

template <class T> T& Stack<T>::top() { if (nextindex <= 0) { error("stack empty"); return data[nextindex - 1]; template <class T> const T& Stack<T>::top() const { if (nextindex <= 0) { error("stack empty"); return data[nextindex - 1]; template <class T> int Stack<T>::getSize() const { return size; 31

int main() { Stack<int> s; Stack<string> s2; s.push(20); s2.push("hello"); Stack<int> s3; s3 = s2; // error cout << s.top() << s2.top() << endl; למה מתקבלת שגיאה? return 0; 32

template<class T, class S> struct Pair { T first; S second; Pair(const T& t, const S& s) : first(t), second(s) { ; ניתן להגדיר תבניות המקבלות יותר מפרמטר אחד Pair<char, double> p('a', 15.0); cout << "(" << p.first << "," << p.second << ")"; List<Pair<string, int>> phonebook; phonebook.add(pair<string, int>("dani",8343434)); phonebook.add(pair<string, int>("rami",8252525)); 33

ניתן להגדיר תבניות גם עם פרמטרים בעלי טיפוס מסוים, :int למשל template<class T, int N> class Vector { T data[n]; public: Vector(); Vector& operator+=(const Vector& v); //... ; וקטור מתמטי ממימד N N נקבע בזמן הקומפילציה, לכן אנו מגדירים למעשה מערך בגודל קבוע כשדה במחלקה void f(vector<int, 3>& v) { Vector<int, 5> v5; Vector<int, 3> v3; v3 += v; // o.k. v5 += v; // error המספר הוא חלק מהטיפוס, לכן <3 Vector<int, ו-< 5 Vector<int, הם טיפוסים שונים נסיון לחבר וקטורים ממימדים שונים לא יתקמפל 34

כאשר הקומפיילר עובר על תבנית הוא יכול למצוא בה רק שגיאות בסיסיות כאשר הקומפיילר יוצר מופע של תבנית יתגלו שגיאות התלויות בארגומנט הספציפי השגיאה המתקבלת מהקומפיילר תהיה מורכבת ממספר שורות ותכלול את רשימת התבניות והארגומנטים שלהן void f() { Stack<Pair<int, int>> ranges(10);..\main.cpp: In constructor `Stack<T>::Stack(int) [with T = Pair<int, int>]':..\main.cpp:241: instantiated from here..\main.cpp:108: error: no matching function for call to `Pair<int, int>::pair()'..\main.cpp:233: note: candidates are: Pair<int, int>::pair(const Pair<int, int>&)..\main.cpp:237: note: Pair<T, S>::Pair(T, S) [with T = int, S = int] בגלל השגיאות המסובכות מומלץ לכתוב תחילה קוד רגיל להמיר אותו לתבנית ורק אחרי שהוא עובד 35

ניתן להגדיר תבנית לפונקציה ניתן להגדיר מחלקות גנריות בעזרת שימוש ב- template בניגוד ל- C כל בדיקות הטיפוסים נעשות בזמן קומפילציה כדי שהשימוש בתבנית יתקמפל על הארגומנטים המועברים לתבנית להיות בעלי כל התכונות הדרושות לפי התבנית ניתן להגדיר תבניות שהפרמטרים שלהן הם מספרים או טיפוסים אחרים ניתן להגדיר תבניות עם מספר פרמטרים )נדיר( מומלץ לכתוב תחילה קוד ללא תבניות ולהמירו אח"כ כדי למנוע התמודדות עם פלט מסובך מהקומפיילר מומלץ להשתמש ב-; T typedef int )או טיפוס אחר במקום )int ולהשתמש ב- T בכל הקוד כדי שההמרה לתבנית תהיה פשוטה 36

שימוש ב- try, catch ו- throw הקצאה על ידי אתחול 37

מנגנון החריגות עובד בעזרת שלושת המילים השמורות try,throw ו- catch : :throw מקבלת כפרמטר את העצם אותו יש לזרוק כחריגה :try מציינת תחילה של בלוק אשר ייתכן ותיזרק ממנו חריגה שנרצה לתפוס :catch מציינת סוג חריגה לתפוס ואת הקוד המתאים לטיפול בחריגה void f(int n) { if (n < 0) { throw -1; int main(int argc, char **argv) { try { f(-7); catch (int e) { cerr << "Error: " << e << endl; כאשר נזרקת חריגה, הפונקציה הנוכחית מפסיקה להתבצע ומתחילה יציאה מכל הפונקציות על המחסנית עד שהחריגה מטופלת אם חריגה לא מטופלת בכלל )נזרקת מ- main ( התכנית תסתיים 38

כאשר חריגה נזרקת מתבצעים הדברים הבאים: כל עוד אנחנו לא בתוך בלוק try קוראים להורסים של המשתנים המקומיים ויוצאים מהפונקציה אם אנחנו בבלוק try בודקים האם קיים catch מתאים אם לא, קוראים להורסים וממשיכים לצאת לטיפוס החריגה שנזרקה אם כן, מתבצע הקוד בבלוק ה- catch ולאחריו הפונקציה שתפסה את החריגה ממשיכה מהשורה שאחרי בלוק ה- catch האחרון ייתכנו מספר בלוקים של catch עבור טיפוסים שונים תהליך היציאה מפונקציות עד לתפיסת שגיאה נקרא התרת המחסנית (stack unwinding) החל מזריקת החריגה ועד לתפיסתה הקוד היחיד שמתבצע הוא של הורסים של המשתנים המקומיים המשוחררים 39

void f(int n) { if (n < 0) { throw -1; void g(int n) { f(-n); void h(int n) { g(2*n); int main() { try { h(7); catch (int e) { cerr << "Error: " << e; 40 השימוש בחריגות מונע כתיבה מיותרת של קוד עבור טיפול בשגיאות בכל פונקציה בדרך מי שיודע לזהות את השגיאה זורק חריגה רק מי שיודע לטפל בשגיאה מתייחס אליה בשימוש בקודי שגיאה כמו ב- C הטיפול במקרי השגיאה נהפך למרבית הקוד ב-++ C ניתן לזרוק כל עצם שהוא אבל נהוג לזרוק רק מחלקות שנוצרו במיוחד כדי לציין שגיאות ספציפיות throw call call call main h g f return return return

template<typename T> class Stack { T * data; int size; int nextindex; public: Stack(int size = 100); Stack(const Stack& stack); ~Stack(); Stack& operator=(const Stack& s); void push(const T& t); void pop(); T& top(); const T& top() const; int getsize() const; ; class Full {; class Empty {; נוסיף חריגות למחסנית הגנרית שלנו: ניתן להגדיר מחלקות בתוך מחלקות template<typename T> void Stack::push(const T& t) { if (nextindex >= size) { throw Full(); data[nextindex++] = t; template<typename T> void Stack::pop() { if (nextindex <= 0) { throw Empty(); nextindex--; 41

void f(stack<int>& s) { try { s.pop(); for (int i = 0; i < 10; ++i) { s.push(i); catch (Stack<int>::Empty& e) { cerr << "No numbers"; catch (Stack<int>::Full& e) { cerr << "Not enough room"; catch (...) { cerr << "Oops"; throw; ניתן להשתמש במספר משפטי catch עבור try יחיד ניתן להשתמש ב-... כדי לתפוס כל חריגה במקרה זה לא ניתן לגשת לחריגה שנתפסה אם כמה מקרים מתאימים לתפיסת החריגה ייבחר הראשון שמופיע לכן... תמיד מופיע אחרון ניתן לזרוק חריגה שנתפסה ב- catch על ידי פקודת throw ללא פרמטרים 42

class String::BadIndex { public: int index; BadIndex(int index) : index(index) { ; void String::verify_index(int index) const { if (index >= size() index < 0) { throw BadIndex(index); return; const char& String::operator[](int index) const { verify_index(index); return data[index]; char& String::operator[](int index) { verify_index(index); return data[index]; טיפוסים של חריגות יכולים להיות יותר מורכבים למשל ניתן לשלוח בהם מידע מדויק על השגיאה בשביל להגדיר מחלקה מקוננת כך יש להכריז עליה בתוך String void f(string& s) { try { cout << s[50]; catch (String::BadIndex& e) { cerr << "Bad Index: " << e.index; 43

Rational::Rational(int n, int d) : num(num), denom(denom) { if (denom == 0) { throw DivideByZero(); int main() { try { while (true) { new int[1000000]; catch (std::bad_alloc& e) { cerr << "Out of memory"; return 0; ניתן לזרוק חריגות מבנאי: אסור לזרוק חריגות מהורס: יכולה להיות רק חריגה אחת בו זמנית בזמן זריקת חריגה הורסים ממשיכים להתבצע אם נזרקת חריגה נוספת התכנית תתרסק כאשר הקצאת זיכרון על ידי new נכשלת נזרקת חריגה מסוג std::bad_alloc 44

לחריגות יש חיסרון חשוב - כל קריאה בקוד שלנו עלולה לגרום לזריקת חריגה )בצורה ישירה או עקיפה( ולכן הקוד צריך להיות מוכן לזריקת חריגה בכל שלב לדוגמה, מה הבעיה באופרטור ההשמה של String שלנו? char* String::allocate_and_copy(const char* str, int size) { return strcpy(new char[size+1], str); String& String::operator=(const String& str) { if (this == &str) { return *this; delete[] data; data = allocate_and_copy(str.data, str.size()); length = str.length; return *this; 45

כאשר מבצעים קוד של שחרור והקצאות - קודם מבצעים את החלק הבעייתי ואח"כ את שחרור המידע הישן: char* String::allocate_and_copy(const char* str, int size) { return strcpy(new char[size+1], str); String& String::operator=(const String& str) { char* temp = allocate_and_copy(str.data, str.size()); delete[] data; data = temp; length = str.length; return *this; למה לא צריך בדיקת השמה עצמית? עדיין קיימת בעיה - מה קורה אם יש שתי הקצאות בבת אחת? 46

כדי להתמודד עם הסכנות הלא צפויות של חריגות נהוג לעטוף את כל הקצאות המשאבים במחלקות בשיטה זו ההורס של המחלקה אחראי לנקות הורסים נקראים אוטומטית, בפרט בזמן התרת המחסנית השימוש בשיטה זו חוסך למתכנת התעסקות מייגעת בהקצאות ושחרורים void good() { string str1; string str2; //... code... void bad() { char* str1 = new char[n+1]; try { char* str2 = new char[n+1]; //... code... catch (bad_alloc& e) { delete[] str1; 47

המנעו מכתיבת קוד אשר משתמש בחריגות כבערכי חזרה המנעו משימוש בחריגות לשם שליטה בקוד המנעו מלהכריח את המשתמשים בקוד שלכם לעשות זאת void good(stack<int>& s) { while(s.getsize() > 0) { cout << s.top() << endl; s.pop(); void bad(stack<int>& s) { while(true) { try { cout << s.top() << endl; s.pop(); catch (Stack<int>::Empty& e) { break; 48

טיפול בשגיאות מתבצע ב-++ C בעזרת try,throw ו- catch אפשר לזרוק כל טיפוס אבל נהוג לזרוק רק עצמים ממחלקות ייעודיות ניתן להשתמש בחריגות במידה ובנאי נכשל שגיאות מהספריה הסטנדרטית, כמו כשלון של new מטופלות על ידי חריגות כדי לשמור על קוד בטוח לחריגות עטפו הקצאות משאבים במחלקות המנעו מכתיבת קוד אשר משתמש בחריגות כבערכי חזרה 49