28
1 ללללל לללללל: Copy constructor Assignment operator תתתת תתתתתתת תתתתתתתתת.- תתתתת תתתתTemplates

1 נושאי התרגול : Copy constructor Assignment operator המרת טיפוסים אוטומטיות. תכנות גנרי - Templates

  • View
    216

  • Download
    0

Embed Size (px)

Citation preview

Page 1: 1 נושאי התרגול : Copy constructor Assignment operator המרת טיפוסים אוטומטיות. תכנות גנרי - Templates

1

:נושאי התרגול

•Copy constructor•Assignment operatorהמרת טיפוסים אוטומטיות.•Templatesתכנות גנרי - •

Page 2: 1 נושאי התרגול : Copy constructor Assignment operator המרת טיפוסים אוטומטיות. תכנות גנרי - Templates

2

Copy constructor & Assignment operator

?s1 = s2מה קורה כאשר מבצעים •?Stack s1 = s2מה קורה כאשר מבצעים •

מה ההבדל? מה הסכנה?מה קורה כאשר קוראים לפונקציה:•

f(Stack s) ;f(Stack& s) ;

- להשמה.assign. Op - לאתחול, copy c’torפתרון •

Page 3: 1 נושאי התרגול : Copy constructor Assignment operator המרת טיפוסים אוטומטיות. תכנות גנרי - Templates

3

Copy constructor & Assignment operator

שתי • אוטומטי באופן מוגדרות חדשה, מחלקה כל עבור פונקציות:

•copy constructor זהו -c’tor המשמש לאתחול של עצם אחד של המחלקה ע"י עצם אחר של

אותה מחלקה. פונקציה זו גם משמשת לאתחל בקריאה לפונקציות, כלומר כאשר פרמטרים

, by valueמעבירים פרמטר מסוג מחלקה מסוימת ערכי השדות של הפרמטרים מאותחלים ע"י

קריאה לפונקציה זאת )כנ"ל לגבי החזרת של פונקציה זו עבור prototypeערכים(. ה-

: הואXמחלקה

X(const X&)X(const X&)

מובטח שלא נשנה את הפרמטר המועבר

copy constructorאי אפשר להגדיר copy constructorבאמצעות

Page 4: 1 נושאי התרגול : Copy constructor Assignment operator המרת טיפוסים אוטומטיות. תכנות גנרי - Templates

4

Copy constructor & Assignment operator

- פונקציה זו משמשת אופרטור ההשמה )=(•להשמה של עצמים מהמחלקה זה לזה פרט

לאתחול של עצם אחד של המחלקה ע"י עצם אחר של אותה מחלקה )במקרה של אתחול ייקרא

, אפילו אם משתמשים בסימן = בביצוע copy c’torה-האתחול(.

בשני המקרים, בפונקצית ברירת המחדל ההעתקה •היא איבר איבר. יש מקרים שבהם העתקה איבר איבר אינה טובה )למשל, במקרה בו יש מצביעים כשדות במחלקה(. במקרים האלה, על המשתמש

להגדיר פונקציות אלו מחדש )דוגמא להגדרה מחדש בהמשך(Stackשל אופרטורים אלו נראה במחלקה

Page 5: 1 נושאי התרגול : Copy constructor Assignment operator המרת טיפוסים אוטומטיות. תכנות גנרי - Templates

5

Copy constructor & Assignment operator

כלל אצבע: בכל מחלקה בה יש שדות •, יש להגדיר מחדש:מצביעיםשהם

• Copy Constructor

• Assignment Operator

• Destructor

Page 6: 1 נושאי התרגול : Copy constructor Assignment operator המרת טיפוסים אוטומטיות. תכנות גנרי - Templates

6

The Final Stack

class Stack {

int* array; int top_index, size;

public:

Stack (int s = 100) ;

Stack (const Stack&) ;

Stack& operator=(const Stack&);

~Stack() ;

Result push(int e);

Result pop() ;

Result top(int& e);

void print() ;

};

Page 7: 1 נושאי התרגול : Copy constructor Assignment operator המרת טיפוסים אוטומטיות. תכנות גנרי - Templates

7

Copy constructor

Stack::Stack(const Stack & st) {

array = new int [st.size];

if (array == 0)

error(“out of memory”); // assumes error exits

size = st.size;

top_index = st.top_index;

for (int top = 0 ; top<st.top_index; top++)

array[top] = st.array[top];

}

Page 8: 1 נושאי התרגול : Copy constructor Assignment operator המרת טיפוסים אוטומטיות. תכנות גנרי - Templates

8

Assignment operatorStack& Stack::operator=(const Stack& st)

{if (this == &st) return *this;

if (st.size != size) {

delete[] array;

array = new int[size = st.size];

}

for (int top = 0 ; top<st.top; top++)

array[top] = st.array[top];

top_index = top;

return *this ;

}

חמשת הצעדים:

בדיקת הצבה עצמית

שחרור משאבים

הקצאת משאבים חדשים

אתחול השדות

*thisהחזרת

Page 9: 1 נושאי התרגול : Copy constructor Assignment operator המרת טיפוסים אוטומטיות. תכנות גנרי - Templates

9

User Defined Type Conversions

קיימים שני סוגי המרות טיפוסים Cב ++אוטומטיות :

• Conversion by constructor.

• Conversion by conversion operator.

Page 10: 1 נושאי התרגול : Copy constructor Assignment operator המרת טיפוסים אוטומטיות. תכנות גנרי - Templates

10

Conversion by construction

אפשר להמיר כל מחלקה T של מחלקה c’torsבעזרת •אחרת או טיפוסים פנימיים של השפה כך שיהפכו

.Tלאיבר מסוג המקבל Constructorההמרה מתבצעת ע”י הגדרת •

ארגומנט יחיד, מהטיפוס הנ”ל. T(class C); //converts from class C to T

על ידי הקומפיילר.אוטומטיתההמרה תתבצע •ההמרה מאפשרת לקרוא לפונקציות המצפות לקבל •

במקום.C עם ארגומנט מטיפוס Tארגומנט מטיפוס דוגמא:

)עוד מעט(double : המרה מ-Complexבמחלקה – )תרגול קודם(String למחלקה const char המרה מ-* –

Page 11: 1 נושאי התרגול : Copy constructor Assignment operator המרת טיפוסים אוטומטיות. תכנות גנרי - Templates

11

Complexדוגמא - המחלקה נניח כי רוצים להגדיר מחלקה של מספרים מרוכבים. היינו רוצים גם

לאפשר את פעולות החשבון הרגילות בין מספרים מרוכבים ומספרים שלמים. דרך אחת לעשות את זה היא להגדיר את כל האפשרויות עבור

כל אופרטור, בדומה לדוגמא הבאה:class complex {

double re,im;public:

complex (double r, double i) {re = r; im = i;}friend complex operator+(complex, complex);friend complex operator+(complex, double);

friend complex operator+(double, complex);

// Do the same for the rest of the operators…};

אותו את לעשות נוספת דרך מיותרות. חזרות ומלאה מייגעת זו שיטה להגדיר היא ל- constructorהדבר complex יחיד פרמטר מקבל אשר

מ doubleמטיפוס ההמרה .double ל complex אוטומטית תתבצע זה.constructorבאמצעות

Page 12: 1 נושאי התרגול : Copy constructor Assignment operator המרת טיפוסים אוטומטיות. תכנות גנרי - Templates

12

Complexדוגמא - המחלקה class complex {

//...

complex(double r) {re = r; im = 0;}

friend complex operator+(complex,complex);

};

המהדר יבצע את ההמרה באופן אוטומטי. לדוגמא:main()

{

complex a;

complex b;

a=b+23;

}

: מה שמתבצע זה ע"י ה- complex מומר ל- 1.23

constructor..complexמתבצע חיבור בין שני .23.a מקבל את התוצאה ע"י אופרטור

ההשמה המוגדר כברירת מחדל ע"י המהדר )העתקה איבר איבר(.

Page 13: 1 נושאי התרגול : Copy constructor Assignment operator המרת טיפוסים אוטומטיות. תכנות גנרי - Templates

13

Conversion by conversion operator אפשר להמיר את Tבעזרת אופרטורים מיוחדים שמוגדרים במחלקה •

T .לטיפוסים פנימיים של השפה או למחלקות אחרות שכבר הוגדרו הדרך היחידה להגדיר המרה לטיפוסים פנימיים של השפה )למה?(.• )מתודה של conversion operatorהמרה זו מבוצעת ע”י הגדרת •

(.Tהמחלקה

operator C() ; // converts from T to C.דוגמא: •

class Price { int Shekel, agorot ; …

public : …. operator double() { return shekel + agorot / 100.0 ;} …

};(.C )של Conversion by constructorאם ניתן רצוי להיעזר ב • בתוכו returnשימו לב שלאופרטור אין ערך החזרה אבל השתמשנו ב-•

)אז מה כן ++Cעם ערך החזרה... מנפלאות הסינטקס של מחזירים?(.

Page 14: 1 נושאי התרגול : Copy constructor Assignment operator המרת טיפוסים אוטומטיות. תכנות גנרי - Templates

14

בעיות עם המרות אוטומטיותclass x { // ...

x(int); x(char*); … };

class y{ //...

y(int); …. };

class z {//...

z(x); …. };

x f(x);

y f(y);

z g(z);

void k1() {

f(1); // Illegal: ambiguous f(x(1)) or f(y(1))

f(x(1));

f(y(1));

g("asdf") ; // Illegal: g(z(x("asdf"))) not tried

g(z("asdf")); // O.k.: x(char*) is carried out

}

עם בעיות שתי קיימות לכך פרטהמרות:

אחת – המרה רק מתבצעתמשמעות – דו להיווצר עלולה(ambiguity)

Page 15: 1 נושאי התרגול : Copy constructor Assignment operator המרת טיפוסים אוטומטיות. תכנות גנרי - Templates

15

המרות ואופרטורים הם בעצם פונקציות. לכן גם עבורם יכולה להתבצע operatorsכזכור •

יכול להיקרא:Complexהמרה. לדוגמה, אופרטור החיבור במחלקה c2 = c1 + 5 ;

לא תתבצע המרה על method אולם אם אופרטור מוגדר כ הארגומנט הראשון שלו. בגלל בעיה זו, עדיף בד"כ להגדיר אופרטור

ע"י פונק' חיצונית. כך, הטיפול בשני האופרנדים יהיה סימטרי.class complex { ...public: complex(double r) {re = r; im = 0;} operator+(const complex&); friend operator-(const complex&, const complex&);};main() {

complex c2,c1; c1=2.0+c2; // Error: 2.0 will not be converted

c2=2.0-c2; // O.k.: 2.0 will be converted}

Page 16: 1 נושאי התרגול : Copy constructor Assignment operator המרת טיפוסים אוטומטיות. תכנות גנרי - Templates

16

Templatesתכנות גנרי -

- מחלקות Containersמשמש בעיקר כאשר בונים •אשר מכילות עצמים אחרים, אולם אין חשיבות

לתכונותיו הייחודיות של אותו עצם: ללא קשר Containerאותן פעולות מוגדרות על ה •

לעצם שבו. לדוגמא עבור מחסנית תמיד יוגדרו :– push– pop– top

.String או int , charללא חשיבות אם זו מחסנית של

Page 17: 1 נושאי התרגול : Copy constructor Assignment operator המרת טיפוסים אוטומטיות. תכנות גנרי - Templates

17

דוגמת המחסניתint_stack.h:class int_stack {

int top_index,size;int* array ;

public:int_stack(int s) ; void pop() ;void push(int e);int top() ;int size();

};

char_stack.h:class char_stack {

int top_index,size;char* array ;

public:char_stack(int s) ; void pop() ;void push(char e);char top() ;int size();

};

String_stack.h:

class string_stack {

int top_index,size;

String* array ;

public:

string_stack(int s) ;

void pop() ;

void push(String e);

String top() ;

int size();

};

Page 18: 1 נושאי התרגול : Copy constructor Assignment operator המרת טיפוסים אוטומטיות. תכנות גנרי - Templates

18

דוגמת המחסנית

int_stack.cc (חלקי):int_stack::int_stack (int s) {

top_index = 0 ; size = s ; array = new int[s];

}

int int_stack::top() {return array[top_index-1];

}

string_stack.cc (חלקי):string_stack::string_stack (int s){

top_index = 0 ; size = s ; array = new String[s];

}

String string_stack::top() {return array[top_index-1];

}

Page 19: 1 נושאי התרגול : Copy constructor Assignment operator המרת טיפוסים אוטומטיות. תכנות גנרי - Templates

19

מחלקות גנריותבכדי להימנע משכפול הקוד (ליתר דיוק: כדי לבצע •

.Templateשכפול קוד מבוקר) נעזר ב מקבל טיפוס(ים) כפרמטר, ויכול Templateה-•

להשתמש בפרמטר שכזה כאילו היה טיפוס רגיל. הנו בעצם תבנית ליצירת מחלקות (מעין Templateה •

את Template“מקרו” מתוחכם). לאחר שהעברנו ל-הטיפוס עמו הוא עובד (ע”י הוספת > טיפוס > לשם

מחלקה רגילה לכל דבר. נקבלTemplateה-

Page 20: 1 נושאי התרגול : Copy constructor Assignment operator המרת טיפוסים אוטומטיות. תכנות גנרי - Templates

20

מה קורה בפועל? כמו שאנחנו כותבים Templateאנחנו כותבים מחלקה שהיא •

>template <class Tמחלקה רגילה, פרט לתוספת השורה לפני הגדרת המחלקה.

Tכעת נוכל לכתוב את קוד המחלקה תוך שאנחנו מתייחסים ל-•כאל טיפוס כלשהו, שיועבר כפרמטר רק מאוחר יותר.

Templateבתוך התוכנית, כאשר אנחנו רוצים להשתמש ב-•, מעבירים את הערך הזה גם כן Tעבור ערך מסוים של

בסוגריים משולשים )ראו דוגמאות בהמשך(.מה שיקרה הוא שבזמן הקומפילציה יתבצע שכפול של הקוד •

ייכתב T ובכל מקום שבו מופיע Templateשכתבנו עבור ה- במקומו.Templateהערך שהועבר ל-

Page 21: 1 נושאי התרגול : Copy constructor Assignment operator המרת טיפוסים אוטומטיות. תכנות גנרי - Templates

21

מחסנית גנריתstack.h:template <class T>class stack {

int top_index,size;T* array ;

public:stack(int s=100) ; void pop() ;void push(T e);T top() ;int size();

};

int_stack.h:

class int_stack {

int top_index,size;

int* array ;

public:

int_stack(int s) ;

void pop() ;

void push(int e);

int top() ;

int size();

};

Page 22: 1 נושאי התרגול : Copy constructor Assignment operator המרת טיפוסים אוטומטיות. תכנות גנרי - Templates

22

מחסנית גנריתstack.h (חלקי):

template <class T<

stack<T<::stack (int s) {

top_index = 0 ; size = s ;

array = new T[s];

}

template <class T<

T

stack<T<:: top() {

return array[top_index-1];

}

int_stack.cc (חלקי):

int_stack::int_stack (int s) {

top_index = 0 ; size = s ;

array = new int[s];

}

int

int_stack::top() {

return array[top_index-1];

}

Page 23: 1 נושאי התרגול : Copy constructor Assignment operator המרת טיפוסים אוטומטיות. תכנות גנרי - Templates

23

שמוש במחסנית הגנריתint main() {

stack<int< si(100);stack<char*< sc(3);

si.push(5);sc.push(“xxx”);sc.push(6); // error !si.size();sc.size();

}

int main() {int_stack si(100);

si.push(5);

si.push(“xxx”); // error !si.size();

}

Page 24: 1 נושאי התרגול : Copy constructor Assignment operator המרת טיפוסים אוטומטיות. תכנות גנרי - Templates

24

Templates

•Templates הינם כלי מאוד שמושי לצורך .Containersהגדרת

ב +Templatesלמרבה הצער המימוש של •+C מזכיר macro חכם ולכן כל הקוד של ה

Template נמצא ב header file כפי שהוצג או ..inline functionכ

ישנן לא רק מחלקות שהן גנריות אלא גם •פונקציות גנריות.

Page 25: 1 נושאי התרגול : Copy constructor Assignment operator המרת טיפוסים אוטומטיות. תכנות גנרי - Templates

25

פונקציות גנריות

int major (int a , int b , int c ) {

if (a == b || a == c) return a ;if (b == c) return b ;exit(1);

}: שימוש

int j = major (1,3,3); // ok?char c = major (‘w’,’w’,’w’);//ok?String s1 = major(s1,s2,s3); //ok ?int j = major (1,’a’,’a’); //ok ?

template <class T<

T

major (T a ,T b , T c ) {

if (a == b || a == c) return a ;

if (b == c) return b ;

exit(1);

}

שימוש :

int j = major (1,3,3); // ok ?

char c= major (‘w’,’w’,’w’); //ok

String s1 = major(s1,s2,s3); // ok?

int j = major (1,’a’,’a’); //ok ?

Page 26: 1 נושאי התרגול : Copy constructor Assignment operator המרת טיפוסים אוטומטיות. תכנות גנרי - Templates

26

Templates - advanced issues

לא “מתעניין” בתכונותיו Templateלמרות ש ה •ניח יכול לההמיוחדות של הטיפוס המועבר כפרמטר הוא

הנחות לגבי קיומם של פונקציות או מתודות מסוימות בו. ? stack ? אילו T על majorאילו הנחות הניח –

ניתן להעביר כמה טיפוסים שונים בפרמטר:•template <class K, class D< class hashtable {

bool find (const K &k, D &d) ;…

};

Page 27: 1 נושאי התרגול : Copy constructor Assignment operator המרת טיפוסים אוטומטיות. תכנות גנרי - Templates

27

Templateפרמטרים ל ל להעביר . Templateניתן פרמטר טיפוס שאינו פרמטר

, קבוע או פונקציה שם מחרוזת להיות :יכולtemplate <class T, int Dim< class Vector {

T vec[Dim] ;…

};

Vector<int, 5< v ; Vector < double, 12 < v1; Vector <Complex, 3< v2; Vector <int , 6< v3 ;

ה שגודל בכך היתרון מהטיפוס ? bufferמה חלק הנוב) יקרה מה ? (v=v3רמז

Page 28: 1 נושאי התרגול : Copy constructor Assignment operator המרת טיפוסים אוטומטיות. תכנות גנרי - Templates

28

Templates - advanced issues הינו טיפוס לכל דבר. אולם templateטיפוס שנוצר ע”י

בדרך כלל כתיבת שמו המלא מסובכת לכן נעזרים בקיצור הבא:

typedef stack<int< stack_int ;

אם נרצה להגדיר מחסנית של מחסניות אזי נגדיר את הטיפוס

typedef stack<stack_int< stack_stack_int;

ונעזר בו:stack_int s1(100);

stack_stack_int s2(5);

s2.push(s1); // in this case push should have better // accepted const T& instead of T ...