תכנות מכוון עצמים ו- C++ יחידה 02 העמסת פונקציות, ערכי ברירת מחדל, enum, קימפול מותנה קרן כליף.

Slides:



Advertisements
Similar presentations
ממיבחניםC שאלות ++.
Advertisements

מבוא למדעי המחשב לתעשייה וניהול
תכנות מונחה עצמים Object Oriented Programming (OOP) אתגר מחזור ב'
מתמטיקה בדידה תרגול 3.
רקורסיות נושאי השיעור פתרון משוואות רקורסיביות שיטת ההצבה
חורף - תשס " ג DBMS, Design1 שימור תלויות אינטואיציה : כל תלות פונקציונלית שהתקיימה בסכמה המקורית מתקיימת גם בסכמה המפורקת. מטרה : כאשר מעדכנים.
תרגול 5 רקורסיות. רקורסיה קריאה של פונקציה לעצמה –באופן ישיר או באופן עקיף היתרון : תכנות של דברים מסובכים נעשה ברור ונוח יותר, מכיוון שזו למעשה צורת.
שאלות חזרה לבחינה. שאלה דיסקים אופטיים מסוג WORM (write-once-read-many) משמשים חברות לצורך איחסון כמויות גדולות של מידע באופן קבוע ומבלי שניתן לשנותו.
מבוא לשפת C חידות ונקודות חשובות נכתב על-ידי יורי פקלני. © כל הזכויות שמורות לטכניון – מכון טכנולוגי לישראל.
תרגול חזרה. מבנה האובייקט תאר את מבנה האובייקט כולל מבנה טבלאות הפונקציות הוירטואליות עבור התכנית הבאה struct A { int x; virtual void a() {}; }; struct.
משטר סטטי שערים לוגיים Wired Drives – © Dima Elenbogen 2009, Moshe Malka :29.
חלון הפקודות מיועד לבצע פעולה אחת בכל פעם. כיצד אפשר לבצע רשימת פקודות או אפליקציות מורכבות ?
1 מבוא למדעי המחשב מבנה של תכנית. 2 מבנה של תכנית – חלוקה לקבצים  תכנית בשפת C הינה אוסף של הגדרות של:  משתנים (חיצוניים)  פונקציות  ניתן לפרוש תכנית.
תכנות תרגול 6 שבוע : תרגיל שורש של מספר מחושב לפי הסדרה הבאה : root 0 = 1 root n = root n-1 + a / root n-1 2 כאשר האיבר ה n של הסדרה הוא קירוב.
מבוא למדעי המחשב מחרוזות, מצביעים וכתובות
11 Introduction to Programming in C - Fall 2010 – Erez Sharvit, Amir Menczel 1 Introduction to Programming in C תרגול
קורס תכנות – סימסטר ב ' תשס " ח שיעור שישי: מערכים
תכנות תרגול 5 שבוע : הגדרת פונקציות return-value-type function-name(parameter1, parameter2, …) הגדרת סוג הערכים שהפונקציה מחזירה שם הפונקציהרשימת.
מערכים עד היום כדי לייצג 20 סטודנטים נאלצנו להגדיר עד היום כדי לייצג 20 סטודנטים נאלצנו להגדיר int grade1, grade2, …, grade20; int grade1, grade2, …, grade20;
עקרון ההכלה וההדחה.
תכנות מונחה עצמים Object Oriented Programming (OOP) אתגר מחזור ב' Templates תבניות.
מבוא לשפת C תרגול 4: ביטויים לוגיים ומשפטי תנאי מבוסס על השקפים שחוברו ע"י שי ארצי, גיתית רוקשטיין, איתן אביאור וסאהר אסמיר עבור הקורס "מבוא למדעי המחשב"
מבוא כללי למדעי המחשב הקצאת זיכרון דינאמית
1 מבוא למדעי המחשב סיבוכיות. 2 סיבוכיות - מוטיבציה סידרת פיבונאצ'י: long fibonacci (int n) { if (n == 1 || n == 2) return 1; else return (fibonacci(n-1)
מבוא למדעי המחשב תרגול 12 – הקצאת זיכרון דינאמית שעת קבלה : יום שני 11:00-12:00 דוא " ל :
11 Introduction to Programming in C - Fall 2010 – Erez Sharvit, Amir Menczel 1 Introduction to Programming in C תרגול
פיתוח מערכות מידע Class diagrams Aggregation, Composition and Generalization.
Methods public class Demonstrate { public static void main (String argv[]) { public static void main (String argv[]) { int script = 6, acting = 9, directing.
מבוא למדעי המחשב לתעשייה וניהול הרצאה 7. סברוטינות subroutines.
תכנות מכוון עצמים ושפת ++C וויסאם חלילי. TODAY TOPICS: 1. Function Overloading & Default Parameters 2. Arguments By Reference 3. Multiple #include’s 4.
מבנים קרן כליף. ביחידה זו נלמד :  מהו מבנה (struct)  איתחול מבנה  השמת מבנים  השוואת מבנים  העברת מבנה לפונקציה  מבנה בתוך מבנה  מערך של מבנים.
מבוא למדעי המחשב לתעשייה וניהול הרצאה 6. מפעל השעווה – לולאות  עד עכשיו  טיפלנו בייצור נרות מסוג אחד, במחיר אחיד  למדנו להתמודד עם טיפול במקרים שונים.
1 Formal Specifications for Complex Systems (236368) Tutorial #1 Course site:
מחרוזות – הטיפוס String
מספרים אקראיים ניתן לייצר מספרים אקראיים ע"י הפונקציה int rand(void);
תכנות מכוון עצמים ו- C++ יחידה 11 תבניות - templates
Computer Architecture and Assembly Language
Operators Overloading
Formal Specifications for Complex Systems (236368) Tutorial #1
Object Oriented Programming
מבוא למדעי המחשב סיבוכיות.
הקצאות דינאמיות בשילוב מבנים
מ- JAVA ל- C קרן כליף.
אבני היסוד של תוכנית ב- JAVA
תוכנה 1 תרגול 13 – סיכום.
מצביעים קרן כליף.
SQL בסיסי – הגדרה אינדוקטיבית
תכנות מכוון עצמים ושפת JAVA
Static and enum קרן כליף.
תכנות מכוון עצמים ו- C++ יחידה 04 constructors, destructor
פונקציות קרן כליף.
מבנים קרן כליף.
פונקציות קרן כליף.
תכנות מכוון עצמים בשפת JAVA
פונקציות קרן כליף.
ניתוח מערכות מידע תכנות ב C#
תכנות מכוון עצמים ושפת JAVA
תכנות מכוון עצמים ושפת JAVA
סוגי משתנים קרן כליף.
תזכורת על מה דיברנו שיעור שעבר? בנינו אתר אינטרנט עם כותרות
מחרוזות קרן כליף.
מערכים של מצביעים הקצאה דינאמית
מבוא לתכנות מונחה עצמים Object Oriented Programming
תוכנה 1 תרגול 13 – סיכום.
תוכנה 1 תרגול 13 – סיכום.
מבוא למדעי המחשב מצביעים.
Computer Programming תרגול 3 Summer 2016
Engineering Programming A
Computer Architecture and Assembly Language
פולימורפיזם מתקדם ממשקים בC# עריכה ועיצוב: קרן הרדי
Presentation transcript:

תכנות מכוון עצמים ו- C++ יחידה 02 העמסת פונקציות, ערכי ברירת מחדל, enum, קימפול מותנה קרן כליף

נכון שזה נכון?? אז די! http://programmingpalace.files.wordpress.com/2011/12/smokingwarningforsoftwareengineers.jpg

ביחידה זו נלמד: ranged based for loop auto string literals העמסת פונקציות ערכי ברירת מחדל לפונקציות enum תזכורת לבעיית ה- include'ים כפולים

Ranged Based For-Loop ניתן לרוץ על לולאה ללא אינדקס! C++11 1 2 3 4 5 void main() { int arr[] = { 1,2,3,4,5 }; for (int x : arr) cout << x << " "; cout << endl; for (int& x : arr) x = x*x; } 1 2 3 4 5 1 4 9 16 25 חסרון: לולאה זו מתאימה רק למערכים עליהם רוצים לעבור באופן סדרתי על כל האיברים מההתחלה לסוף (אי אפשר למשל לעבור רק על מיקומים זוגיים וכד')

על משתנה מטיפוס זה ניתן להפעיל את הפונקציה name() שמחזירה את שם הטיפוס auto C++11 ניתן להגדיר משתנים ללא טיפוס ספציפי! typeid היא פונקציה המקבלת משתנה או טיפוס ומחזירה משתנה מטיפוס type_info, המחזיק מידע על טיפוס. על משתנה מטיפוס זה ניתן להפעיל את הפונקציה name() שמחזירה את שם הטיפוס void main() { auto a = 5; auto* b = &a; auto c = &a; auto& d = a; auto x; cout << typeid(a).name() << endl; cout << typeid(b).name() << endl; cout << typeid(c).name() << endl; cout << typeid(d).name() << endl; d = 3; cout << a << " " << d << endl; char ch = 'a'; c = ch; } טיפוסו של המשתנה נקבע מיד עם אתחולו ולכן חייב להיות ידוע בזמן קומפילציה int int * 3 3 // cannot convert from 'char' to 'int *'

auto + ranged for loop void main() { char* daysOfWeek[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; for (auto day : daysOfWeek) cout << day << " "; cout << endl; }

Raw String Literals C++11 כדי להציג למסך תווים מיוחדים (גרשיים, גרש, סלש וכד') יש לשים לפניהם \, מה שלפעמים יכול להיות מעיק, וכן להציג טקסט עם ירידות שורה הפתרון הוא Raw String Literals! void main() { char* s1 = "\"Hello World\""; cout << s1 << endl; char* s2 = R"("Hello World")"; cout << s2 << endl; char* s3 = "\"foo()\""; cout << s3 << endl; char* s4 = R"("foo()")"; char* s4 = R"##("foo()")##"; cout << s4 << endl; } נעטוף את הטקסט שנרצה שיוצג ב- R”(The Text)” "Hello World" "foo()" הבעיה: יש את הרצף "( בתוך הטקסט הפתרון: לעטוף את הסוגריים ברצף כלשהו לבחירתכם (פה בחרתי ##)

העמסת פונקציות (Functions Overloading) כלומר, ניתן להגדיר פונקציות דומות עם שם זהה, המקבלות טיפוסים שונים דוגמה: void swap(int& a, int& b) { int temp = a; a = b; b = temp; void swap(char& a, char& b) char temp = a; void main() } int n1=3, n2=6; swap(n1, n2); char ch1='a', ch2='z'; swap(ch1, ch2); {

בעית דו-משמעות (ambiguity) הקומפיילר אינו יכול להבדיל בין 2 פונקציות הנבדלות אך ורק בערך המוחזר הסיבה: לא בהכרח יהיה שימוש בערך המוחזר דוגמה: int foo() {return 0;} char foo() {return 'a';} void main() { foo(); הקומפיילר לא ידע לאיזו גרסא לפנות, ונקבל שגיאת ambiguity: error C2371: 'foo' : redefinition; different basic types

בעית דו-משמעות (ambiguity) (2) גם במקרה זה הקומפיילר לא ידע לאיזו גרסה לפנות: void foo(double d) {} void foo(float f) {} void main() { double d = 5.2; float f = 7.3f; foo(d); foo(f); } void foo(double d) {} void foo(float f) {} void main() { int x=3; foo(x); דוגמא תקינה error C2668: 'foo' : ambiguous call to overloaded function הקומפיילר לא יודע אם להמיר את x ל- double או ל- float בעיית ה- ambiguity אינה בעיה של הפונקציות, אלא של אופן הקריאה, שאינו מורה לקומפיילר באופן חד-משמעי לאיזו גרסא לפנות

ערכי ברירת מחדל (default values) בשפת C++ ניתן לתת ערך ברירת מחדל לפרמטרים האחרונים שהפונקציה מקבלת, ובכך יהיה ניתן בשימוש להחסיר ארגומנטים אלו התוצאה היא העמסת הפונקציה void printChar(char ch='*', int times=5); void main() { printChar('#', 3); printChar('@'); printChar(); void printChar(char ch, int times) } for (int i=0 ; i < times ; i++) cout << ch; cout << endl; במקרה של הפרדה בין ההצהרה למימוש, ערכי ברירת המחדל יכתבו בהצהרה העמסת 3 פונקציות במחיר מימוש של אחת 

ערכי ברירת מחדל (2) void printChar(char ch='*', int times=5); void printChar(int times, char ch='*'); void main() { printChar('#', 3); printChar('@'); printChar(); printChar(8); void printChar(char ch, int times) } for (int i=0 ; i < times ; i++) cout << ch; cout << endl; void printChar(int times, char ch) printChar(ch, times); נשים לב כי לא ניתן לתת ערך ב"מ לפרמטר times, משום שנקבל שגיאת ambiguity במידה ויקראו לפונקציה ללא פרמטרים קריאה לפונקציה הראשונה קריאה לפונקציה השניה לא ניתן היה להגדיר את את הפונקציה הבאה: void printChar(int times=5, char ch); משום שערכי ב"מ ניתן לתת רק לפרמטרים האחרונים ברשימה. אחרת, הקריאה לפונקציה תצטרך להיות: printChar( , ‘*’) וזה לא תקין

enum הגדרת טיפוס חדש שיכיל ערך מספרי מתוך קבוצה מוגדרת מראש כלומר, הגדרת אוסף קבועים בעלי קשר לוגי למשל: ימות השבוע, אוסף צבעים, ערכים בוליאנים וכד' דוגמה: enum eColor {RED, YELLOW, BLUE}; זוהי הגדרה של 3 קבועים, הראשון מקבל באופן אטומטי את ערך 0, זה שאחריו את ערך 1 וכו'. כעת נוכל להגדיר בתוכנית משתנים מטיפוס color ולתת להם את הערכים RED/YELLOW/BLUE

enum - מתן ערך שגוי אם ניתן למשתנה מטיפוס ה- enum ערך מספרי שאינו הוגדר בקבוצת הערכים שלו, נראה את הערך המספרי (לא נקבל שגיאה) קליטה לתוך enum צריכה להתבצע לתוך int ואז לבצע המרה enum eColor {RED, YELLOW, BLUE}; void main() { eColor c1 = RED; cout << "c1=" << c1 << endl; eColor c2 = (eColor)5; cout << "c2=" << c2 << endl; eColor c3; //cin >> c3; int colorNum; cin >> colorNum; c3 = (eColor)colorNum; } הקומפיילר לא מבצע casting מ- int לטיפוס החדש, לכן צריך לעשות המרה מפורשת

טריק לקבלת שמו של enum ניתן להגדיר מערך גלובלי של מחרוזות עם שמות ה- enum בהתאמה לערכיהם enum eColor { White, Black, Red, Yellow, Blue }; const char* colors[] = { "White", "Black", "Red", "Yellow", "Blue" }; void main() { eColor c = Red; cout << "Selected color is " << colors[c] << endl; }

מאחר ולא נתנו ל- Red ערך, ערכו יהיה ערך עוקב לקבוע שלפניו enum – מתן ערכים שונים ניתן לכל ערך באוסף לתת ערך שאינו עוקב לערך שלפניו, ע"י השמה: מאחר ולא נתנו ל- Red ערך, ערכו יהיה ערך עוקב לקבוע שלפניו enum eColor { White = 10, Black = 20, Red, Yellow = 40, Blue = 50 }; void main() { eColor c1 = (eColor)1, c2 = (eColor)20, c3 = (eColor)21, c4 = (eColor)45; }

Enhanced Enums enum eColor { Red, Yellow, Green }; enum eGrades:char {A, B, C}; //enum eGrades:char { 'A', 'B', 'C' }; void main() { eColor c1 = Red; eColor c2 = eColor::Red; char mathGrade = eGrades::A; cout << "Math grade is " << mathGrade << endl; char physicsGrade = eGrades::B + 'A'; cout << "Physics grade is " << physicsGrade << endl; } הערכים תמיד צריכים להיות מאותחלים כמספרים ניתן (ועדיף!) לפנות לערך בקבוצה עם שם הטיפוס. יותר קריא! למרות שהגדרנו את הטיפוס כ- char, הערכים סדרתיים ומתחילים מ- 0 Math grade is Physics grade is B

Enhanced Enums - הפתרון enum eGrades:char { A='A' , B, C}; void main() { char mathGrade = eGrades::A; cout << "Math grade is " << mathGrade << endl; char physicsGrade = eGrades::B/* + 'A'*/; cout << "Physics grade is " << physicsGrade << endl; } Math grade is A Physics grade is B

Enum Classes ניתן להגדיר את ה- enum כ- class, ואז חלות עליו מספר הגבלות enum class eSeason {Winter, Spring, Summer, Fall }; void main() { int s1 = eSeason::Summer; int s2 = (int)eSeason::Winter; int s3 = Fall; } אין המרה אוטומטית ל- int הפניה לערך חייבת להיות לכלול את שם המחלקה

תזכורת: פעולת ה- include פעולת ה- include היא פקודת קדם-מעבד (preprocessor) אשר שותלת בקוד במקום כל פקודת include את תוכן הקובץ שאותו כללנו בפקודה a.h struct A { int x; }; struct A { int x; }; void main() } main.cpp #include "a.h" void main() } {

הבעיתיות בפקודת include a.h struct A { int x; }; struct A { int x; }; // prototypes void foo(); void main() } נקבל שגיאה של redefinition מאחר והקומפיילר רואה את ההצהרה על המבנה שמוגדר ב- a.h יותר מפעם אחת b.h #include "a.h" // prototypes void foo(); main.cpp #include "a.h" #include "b.h" void main() } {

הפתרון: הידור מותנה ראינו בעבר את הפקודה #define לצורך הגדרת קבוע מסוים פקודה זו מוסיפה את הקבוע שהוגדר לטבלת סימולים של התוכנית במידה וטרם הוגדר. במידה וכבר הוגדר דורסת את ערכו. ניתן גם לכתוב פקודת define ללא ערך, רק כדי להכניס קבוע מסוים לטבלת הסימולים ניתן לבדוק האם קבוע מסוים הוגדר בטבלת הסימולים בעזרת הפקודה #ifdef או אם לא הוגדר בעזרת הפקודה #ifndef במידה והתנאי מתקיים, הקופיילר יהדר את קטע הקוד הבא עד אשר יתקל ב- #endif

כעת יש לנו ב- main פעם אחת בלבד את ההגדרות מכל קובץ הפתרון עם הידור מותנה a.h b.h #ifndef __A_H #define __A_H struct A { int x; }; #endif // __A_H #ifndef __B_H #define __B_H #include "a.h" // prototypes void foo(); #endif // __B_H main.c לאחר preprocessor struct A { int x; }; // prototypes void foo(); void main() } foo(); כעת יש לנו ב- main פעם אחת בלבד את ההגדרות מכל קובץ main.cpp #include "a.h" #include "b.h" void main() } foo(); { טבלת הסימולים: __A_H __B_H

הקומפיילר אינו מכיר את הטיפוס A ולכן שגיאת הקומפילציה... בעיה נוספת ב- include כאשר יש 2 מבנים אשר כל אחד מגדיר אובייקט מטיפוס המבנה השני, מתקבלת שגיאת קומפילציה שקשה להבינה: #ifndef __A_H #define __A_H #include "b.h" struct A { B b; }; #endif // __A_H #ifndef __B_H #define __B_H #include "a.h" struct B { A a; }; #endif // __B_H הקומפיילר אינו מכיר את הטיפוס A ולכן שגיאת הקומפילציה... #include "a.h" #include "b.h" void main() } { טבלת הסימולים: __A_H __B_H

הצהרה שהמחלקה תוגדר בהמשך הפתרון במקרה זה נדאג שלפחות אחד המבנים יכיל רק מצביע למבנה השני, ולא אובייקט כאשר יוצרים אובייקט צריך לבצע include לקובץ המגדיר אותו כאשר יש מצביע לאובייקט לא חייבים לבצע include לקובץ המכיל אותו, אלא להסתפק בהצהרה שמבנה זה יוגדר בהמשך בקובץ cpp בו תהיה היצירה של האובייקט נבצע את ה- include לקובץ בו מוגדר המבנה #ifndef __A_H #define __A_H #include "b.h" struct A { B b; }; #endif // __A_H #ifndef __B_H #define __B_H struct A; struct B { A* a; }; #endif // __B_H הצהרה שהמחלקה תוגדר בהמשך

ביחידה זו למדנו: ranged based for loop auto string literals העמסת פונקציות ערכי ברירת מחדל לפונקציות enum תזכורת לבעיית ה- include'ים כפולים