240 likes | 450 Vues
תכנות מכוון עצמים ושפת ++ C. וויסאם חלילי. TODAY TOPICS: 1 . Function Overloading & Default Parameters 2. Arguments By Reference 3. Multiple # include’s 4. Inline Functions. Function Overloading & Default Parameters. void foo( int i , int j ) } //foo1
E N D
תכנות מכוון עצמים ושפת ++C וויסאם חלילי
TODAY TOPICS:1. Function Overloading & Default Parameters2. Arguments By Reference3. Multiple #include’s4. Inline Functions
Function Overloading & Default Parameters voidfoo(inti, int j)}//foo1 cout<< "I'm the foo that returns void" << endl; } void foo(inti, int j=1)}//foo2 cout<< "I'm the foo that returns void with default parameter" << endl; } void foo(inti)}//foo3 cout<< "I'm the foo that returns void with one parameter" << endl; } intfoo(inti, int j)}//foo4 cout<< "I'm the foo that returns int" << endl; return7; }
Function Overloading & Default Parameters voidfoo(inti, int j)}//foo1 cout<< "I'm the foo that returns void" << endl; } void foo(inti, int j=1)}//foo2 cout<< "I'm the foo that returns void with default parameter" << endl; } void foo(inti)}//foo3 cout<< "I'm the foo that returns void with one parameter" << endl; } intfoo(inti, int j)}//foo4 cout<< "I'm the foo that returns int" << endl; return7; } אילו פונקציות לא יכולות לחיות יחד?
Back to Pointers & const מי מהביטויים חוקי ומי לא? void fun(constchar * str)} str= "dd"; str[0]='a'; } void fun(charconst * str)} str= "dd"; str[0]='a'; } void fun(char * conststr)} str= "dd"; str[0]='a'; }
Back to Pointers & const void fun(constchar * str)} str= "dd"; str[0]='a'; //forbidden: str is a pointer to constant argument } void fun(charconst * str)} str= "dd"; str[0]='a'; //forbidden: str is a pointer to constant argument } void fun(char * conststr)} str= "dd"; //forbidden: the "str" argument itself is a constant argument str[0]='a'; }
Arguments By Reference voidswap(intx, inty)} inttemp = x; x=y; y=temp; } void main()} intarr[] = {1, 6, 34, 28, 73}; intsize = sizeof(arr)/sizeof(arr[0]); intindex1, index2; cout<< "This is the array: "; printArr(arr, size); cout<< "Please give two indexes to swap <0-4>: "; cin>> index1>> index2; swap(arr[index1],arr[index2]); cout << "This is the array after swapping: "; printArr(arr, size); } voidprintArr(int* arr, int size)} for(inti=0; i<size; i++)} cout<< arr[i] << ", "; cout<< endl; } קלט: 2,4 פלט: ?
Arguments By Reference קלט: 2,4 פלט: 1, 6, 34, 28, 73 תיקון לפונקציה: voidswap(int&x, int&y) } inttemp = x; x=y; y=temp; }
Return By Reference EX1 #include<iostream> usingnamespacestd; // should be <1-5> intglobalVar = -1; int& getGlobalVar() } returnglobalVar; } void main() } getGlobalVar() = 4; cout<< getGlobalVar() << endl; } פלט: ?
Return By Reference EX1 #include<iostream> usingnamespacestd; // should be <1-5> intglobalVar = -1; int& getGlobalVar() } returnglobalVar; } void main() } getGlobalVar() = 4; cout<< getGlobalVar() << endl; } פלט: 4
Return By Reference EX2 #include<iostream> usingnamespacestd; // should be <1-5> intglobalVar = -1; int& getGlobalVar() } inti = globalVar; returni; } void main() } getGlobalVar() = 4; cout<< getGlobalVar() << endl; } פלט: ?
Return By Reference EX2 #include<iostream> usingnamespacestd; // should be <1-5> intglobalVar = -1; // this is wrong !!! // can't return local variable ByRef ! // Should be compilation error, but VC++6.0 // accepts it and gives a warning // (anyway it's WRONG) int& getGlobalVar() } inti = globalVar; returni; //warning C4172: returning address of local variable or temporary } פלט: אסור להחזיר reference למשתנה מקומי (על ה stack)
Return By Reference EX3 #include<iostream> usingnamespacestd; // should be <1-5> intglobalVar = -1; int& getGlobalVar() } int& i = globalVar; returni; } void main() } getGlobalVar() = 4; cout<< getGlobalVar() << endl; } פלט: ?
Return By Reference EX3 #include<iostream> usingnamespacestd; // should be <1-5> intglobalVar = -1; // here i is a reference to globalVar // and this is fine int& getGlobalVar() } int& i = globalVar; returni; } פלט: 4
Return By Reference EX4 // should be <1-5> intglobalVar = -1; constint& getGlobalVar() } switch(globalVar){ case 1: return 1; case 2: return 2; case 3: return 3; case 4: return 4; case 5: return 5; default: return -1; } return -1; } void main()} globalVar= 4; cout<< getGlobalVar() << endl; } פלט: ?
Return By Reference EX4 #include<iostream> usingnamespacestd; // should be <1-5> intglobalVar = -1; // returning is a number and not variable // warning C4172: returning address of local variable or temporary constint& getGlobalVar() } switch(globalVar){ case 1: return 1; case 2: return 2; case 3: return 3; case 4: return 4; case 5: return 5; default: return -1; } return -1; } פלט: 4
תזכורת: פעולת ה- include • פעולת ה- include היא פקודת קדם-מעבד (preprocessor) אשר שותלת בקוד במקום כל פקודת include את תוכן הקובץ שאותו כללנו בפקודה a.h // prototypes void aFoo1(); int aFoo2(); #include <iostream> // prototypes void aFoo1(); int aFoo2(); void main() } aFoo1(); aFoo2(); { main.cpp #include <iostream> #include "a.h" void main() } aFoo1(); aFoo2(); {
הבעיתיות בפקודת include a.h // prototypes void aFoo1(); int aFoo2(); יתכן ונעשה include לקובץ מסוים יותר מפעם אחת: #include <iostream> // prototypes void aFoo1(); int aFoo2(); // prototypes void aFoo1(); int aFoo2(); // prototypes Void bGoo1(); int bGoo2(); void main() } aFoo1(); bGoo1(); { b.h #include “a.h” // prototypes void bGoo1(); int bGoo2(); נקבל שגיאה של redefinition מאחר והקומפיילר רואה את ההצהרה על הפונקציות שמוגדרות ב- a.h יותר מפעם אחת מ- a.h main.cpp מ- b.h #include <iostream> #include "a.h“ #include “b.h“ void main() } aFoo1(); bGoo1(); {
הפתרון: הידור מותנה • ראינו בעבר את הפקודה #define לצורך הגדרת קבוע מסוים • פקודה זו מוסיפה את הקבוע שהוגדר לטבלת סימולים של התוכנית במידה וטרם הוגדר. במידה וכבר הוגדר דורסת את ערכו. • ניתן גם לכתוב פקודת define ללא ערך, רק כדי להכניס קבוע מסוים לטבלת הסימולים • ניתן לבדוק האם קבוע מסוים הוגדר בטבלת הסימולים בעזרת הפקודה #ifdef או אם לא הוגדר בעזרת הפקודה #ifndef • במידה והתנאי מתקיים, הקופיילר יהדר את קטע הקוד הבא עד אשר יתקל ב- #endif
הפתרון עם הידור מותנה a.h b.h #ifndef __A_H #define __A_H // prototypes void aFoo1(); int aFoo2(); #endif// __A_H #ifndef __B_H #define __B_H #include “a.h” // prototypes void bGoo1(); int bGoo2(); #endif// __B_H main.cppלאחר preprocessor #include <iostream> // prototypes void aFoo1(); int aFoo2(); // prototypes void bGoo1(); int bGoo2(); void main() } aFoo1(); bGoo1(); { main.cpp כעת יש לנו ב- main פעם אחת בלבד את ההגדרות מכל קובץ #include <iostream> #include "a.h“ #include “b.h“ void main() } aFoo1(); bGoo1(); { טבלת הסימולים: __A_H __B_H
בעיה נוספת ב- include כאשר יש 2 מבנים אשר כל אחד מגדיר אובייקט מטיפוס המבנה השני, מתקבלת שגיאת קומפילציה שקשה להבינה: #ifndef __A_H #define __A_H #include “b.h” structA { B b; }; #endif// __A_H #ifndef __B_H #define __B_H #include “a.h” structB { 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” structA { B b; }; #endif// __A_H #ifndef __B_H #define __B_H structA; structB { A* a; }; #endif// __b_H הצהרה שהמחלקה תוגדר בהמשך
Inline #ifndef_INLINE_FUNCTION_H_ #define_INLINE_FUNCTION_H_ #include<iostream> usingnamespace std; // this is an example of inline function // (should be in .h file! otherwise you may get linker errors) inlinevoidfoo() { cout << "foo" << endl; } #endif inlineFunction.h #include"inlineFunction.h" void main() { foo(); } inlineFunction.cpp
Inline equivalent Inline Function inlinevoid foo(intstartTime, intendTime, int& deltaTime) { deltaTime= endTime - startTime; } void main() { intelapsedTime = 0; foo(21,24,elapsedTime); } void main() { intelapsedTime = 0; { intstartTime=21; intendTime=24; int& deltaTime= elapsedTime; deltaTime= endTime - startTime; } } The equivalent