Similar presentations:
תכנות מכוון עצמים ו++C - יחידה 01 מ C -ל++C - קרן כליף
1.
תכנות מכוון עצמים ו++C -יחידה 01
מ C -ל++C -
קרן כליף
2.
:ביחידה זו נלמד הגדרת תכנות מכוון עצמים
:++C - לC השוני הסינטקטי בין
printf cout
scanf cin
gets cin.getline
malloc new
free delete
טיפוס התייחסות
)namespace( מרחבי שמות
© Keren Kalif
2
3.
מה אנחנו יודעים? תכנות פרוצדורלי בקורס Cלמדנו לתכנת במתודלוגיה הנקראת תכנות פרוצדורלי
התכנות היה בסגנון Top-Down
הדגש בתוכניות היה על פונקציות והמידע המועבר בינהן
דוגמא:
אם רצינו לטפל במטריצה ,היינו רושמים את הפונקציות הבאות:
פונקציה שיודעת להקצות מטריצה
פונקציה שיודעת לקלוט נתונים למטריצה
פונקציה שיודעת להדפיס את המטריצה
פונקציה שיודעת לשחרר את נתוני המטריצה
כל אחת מהפונקציות הנ"ל הייתה צריכה לקבל את המטריצה
ומימדיה כפרמטרים
3
© Keren Kalif
4.
מה נלמד? תכנות מכוון עצמים בקורס זה נלמד מתודולוגית תכנות הנקרא "תכנות מכוון עצמים"
( ,Object Orientedאו בקיצור )OO
הדגש יהיה על האובייקטים שיש במערכת ,מה המידע שיש לכל
אובייקט ,ומה הפעולות שכל אובייקט יודע לבצע
כמו structשל ,Cאבל בנוסף לשדות ,יהיו גם פעולות
מתודולוגיית תכנות זו מייצגת כיצד העולם שלו בנוי
דוגמא:
לסטודנט יהיו את השדות :ת.ז ,שם ,תאריך לידה ,מגמת לימוד
וממוצע
בנוסף ,הוא ידע לבצע את הפעולות הבאות :להירשם לקורס ,להדפיס
את נתוניו ,ללמוד למבחן ,להכין מטלות וללכת לים
4
© Keren Kalif
5.
לתכנות מכוון עצמים 3עקרונות מרכזיים .1הסתרה ) :(encapsulationכל הנתונים והפעולות הקשורות
לישות מסוימת מרוכזות יחדיו .המשתמש עובד עם "קופסא
שחורה".
יתרונות :קל ללמוד את הקוד ולהתמצא בו ,תחזוקה פשוטה
.2הורשה ) :(inheritanceהרחבה של ישות קיימת כדי למנוע שכפול
קוד ,או לחילופין כדי לתת מימוש אלטרנטיבי לקוד קיים.
למשל :ל person -יש אוסף נתונים ,ול student -יש בדיוק אותם
נתונים ועוד כמה נוספים .לא נרצה לשכפל את כל הקוד שיש ב-
..person
.3רב-תצורתיות (פולימורפיזם :)polymorphism ,מאפשר להתייחס
לישויות שונות בעלי בסיס זהה באותו אופן.
למשל :החזקת מערך של צורות ,כאשר חלק מהצורות הן ריבוע,
חלקן עיגול או משולש ,ולהיות מסוגלים להדפיס את כולן.
5
© Keren Kalif
6.
תכנות מכוון עצמים ו++C -בנוסף ל 3 -העקרונות שראינו קודם ,בשפת ++Cיש 2עקרונות
נוספים:
.1תבניות ) :(templatesכלי המאפשר לכתוב קוד כללי לטיפוסים
שונים.
דוגמא :האלגוריתם למיון קבוע לכל טיפוס ,אבל המערך המתקבל
ופעולות ההשוואה מבוצעות על טיפוסים שונים.
במקום לשכפל את הקוד עבור טיפוס שונה כל פעם ,ניתן לכתוב
פונקציה כללית אחת שתדע לטפל בכל טיפוס.
.2חריגות ) :(exceptionsמנגנון לטיפול שגיאות בזמן ריצה.
6
© Keren Kalif
7.
מ C -ל++C - שפת ++Cמאוד דומה סינטקטית לשפת ,Cאך יחד עם זאת
יש כמה שינויים:
נפתח פרויקט באותו אופן כמו בקורס ,Cאבל נייצר קובץ עם
סיומת ( cppברירת המחדל) ,ולא עם סיומת c
הקומפיילר שונה ,ולכן יתכנו שגיאות קומפילציה טיפה שונות
7
ניתן להגדיר משתנים בכל חלק בתוכנית ,ולא רק בתחילת בלוק
במקום הכללת הספריה stdio.hשהכילה פקודות קלט-פלט ,נכליל
את הספריה iostreamונוסיף ;( using namespace stdהסבר
בהמשך)
קיים הטיפוס boolשמחזיק את הערכים trueאו false
© Keren Kalif
8.
מ C -ל)2( ++C - .5פקודות שונות לטיפול בקלט ופלט:
במקום הפקודה printfנשתמש בפקודה cout
במקום הפקודה scanfנשתמש בפקודה cin
.6פקודות שונות לטיפול בהקצאות ושחרור זכרון:
במקום הפקודות malloc/callocנשתמש בפקודה new
במקום הפקודה freeנשתמש בפקודה delete
8
© Keren Kalif
9.
.. שאני לא אתעצבן,אבל ראשיתhttp://qph.is.quoracdn.net/main-qimg-e0c9dafb319150b6c6d9816047ed9eae?convert_to_webp=true
© Keren Kalif
9
10.
cout הפקודה(Console OUT) יודעת להדפיס נתונים למסך
אין צורך להבדיל בהדפסה:printf - הסינטקס הרבה יותר פשוט מ
משרשרים את חלקי המחרוזת להדפסה,בין הטיפוסים השונים
>> באמצעות
#include <stdio.h>
#include <iostream>
using namespace std;
void main()
{
char str[] = "hi";
int num = 5;
printf("string: %s number: %d\n",
str, num);
{
void main()
{
char str[] = "hi";
int num = 5;
cout << "string: " << str << " number: "
<< num << "\n";
}
© Keren Kalif
10
11.
cin הפקודה(Console IN) יודעת לקרוא נתונים מהמקלדת
אין צורך להבדיל בקליטה:scanf - הסינטקס הרבה יותר פשוט מ
משרשרים את הנתונים השונים שרוצים,בין הטיפוסים השונים
<< לקרוא באמצעות
#include <stdio.h>
#include <iostream>
using namespace std;
void main()
{
char str[10]
int num;
printf("Enter string and number: ");
scanf("%s%d", str, &num);
{
void main()
{
char str[10];
int num;
cout << "Enter string and number: ";
cin >> str >> num;
}
© Keren Kalif
11
12.
cin.getline הפקודה יודעת לקרוא מחרוזת עד רווחcin
או עדENTER ניתן לקלוט תווים עדcin.getline - ע"י שימוש ב
למקסימום תווים
#include <stdio.h>
#include <iostream>
using namespace std;
void main()
{
char str[10];
printf("Enter string: ");
gets(str);
{
void main()
{
char str[10];
cout << "Enter string: ";
cin.getline(str, 5);
}
תווים4 הפונקיה תקרא עד
)'\0' -(אחד עבור ה
ENTER או עד
© Keren Kalif
12
13.
delete - וnew הפקודות מקצה מערך עם ערכי זבל, להקצאה דינאמיתnew הפקודה
)malloc -(מקבילה ל
calloc - אין מקבילה ל
realloc - אין מקבילה ל
אם משחררים מערך יש לשחרר. לשחרור זכרוןdelete הפקודה
][ עם
#include <stdio.h>
#include <iostream>
#include <stdlib.h>
using namespace std;
void main()
{
int *arr, numOfElements;
void main()
{
int *arr, numOfElements;
printf("How many elements? ");
scanf("%d", &numOfElements);
arr = (int*)malloc(numOfElements*sizeof(int));
free(arr);
}
cout << "How many elements? ";
cin >> numOfElements;
arr = new int[numOfElements];
delete []arr;
}
© Keren Kalif
13
14.
דוגמא#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
void main()
{
int i, numOfNumbers;
int* arr;
void main()
{
int numOfNumbers;
printf("How many numbers? ");
scanf("%d", &numOfNumbers);
cout << "How many numbers? ";
cin >> numOfNumbers;
arr = (int*)calloc(numOfNumbers, sizeof(int));
for (i=0 ; i < numOfNumbers ; i++)
printf("Value #%d: %d\n", i+1, arr[i]);
int* arr = new int[numOfNumbers];
for (int i=0 ; i < numOfNumbers ; i++)
cout << "Value #" << i+1 << ": " << arr[i] << "\n";
free(arr);
delete []arr;
}
{
נשים לב להגדרת המשתנים באמצע התוכנית
© Keren Kalif
14
15.
תוכנית המטפלת במטריצה:דוגמא1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
#include <iostream>
using namespace std;
const int N = 3;
const int M = 4;
// prototypes
int** allocateMatrix
void enterInput
void printMatrix
void freeMatrix
(int rows, int cols);
(int** mat, int rows, int cols);
(int** mat, int rows, int cols);
(int** mat, int rows);
void main()
{
int** mat = NULL;
כתוב בראשי פרקים וניתןmain -ה
להבין בקלות מה קורה בתוכנית
mat = allocateMatrix(N, M);
enterInput(mat, N, M);
printMatrix(mat, N, M);
freeMatrix(mat, N);
{
© Keren Kalif
15
16.
)2( תוכנית המטפלת במטריצה:דוגמא22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
int** allocateMatrix(int rows, int cols)
עבור השורות,int* בתחילה מקצים מערך של
}
int** mat = new int*[rows]; // allocating the rows
for (int i=0 ; i < rows ; i++)
mat[i] = new int[cols]; // allocating the columns
return mat;
{
void enterInput(int** mat, int rows, int cols)
}
for (int i=0 ; i < rows ; i++)
for (int j=0 ; j < cols ; j++)
mat[i][j] = i*cols + j;
{
נשים לב לאפשרות הגדרת
המשתנים בכל חלק בקוד
© Keren Kalif
16
17.
)3( תוכנית המטפלת במטריצה:דוגמא37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
void printMatrix(int** mat, int rows, int cols)
{
for (int i=0 ; i < rows ; i++)
}
for (int j=0 ; j < cols ; j++)
cout << mat[i][j] << ", ";
cout << "\b\b \n";
{
{
void freeMatrix(int** mat, int rows)
}
for (int i=0 ; i < rows ; i++)
delete []mat[i];
] [ שחרור מערך עם ציון:נשים לב
delete []mat;
{
© Keren Kalif
17
18.
טיפוס התייחסות בשפת Cכאשר רצינו שפונקציה תשנה את ערכו של ארגומנט
מסוים ,העברנו את הכתובת שלו (העברה ,by pointerלעומת
העברת העתק)by value ,
בשפת ++Cעדיין ניתן להעביר מצביעים כדי לשנות ארוגמנטים
בפונקציות ,אך יש דרך חדשה הנקראית העברת פרמטרים by
reference
בהגדרת הפרמטרים שהשיטה מקבלת מציינים ליד הפרמטר &
זהו למעשה מתן שם נוסף לארגומנט המקורי שנשלח הנגיש מתוך
הפונקציה
אין הבדל סינטקטי בשליחת המשתנה בעבור משתנה שעובר by
valueאו by reference
18
© Keren Kalif
19.
1.2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
void changeTo4byVal(int x)
{
x = 4;
{
by ref שליחת פרמטר
by val לעומת
void changeTo4byRef(int& x)
}
x = 4;
}
10
4
int: x
chagneTo4ByVal -הזכרון של ה
int: x
void main()
}
int num = 10;
cout << "orig num = " << num << endl;
2000
???
chagneTo4ByRef -הזכרון של ה
4
10
int: num
1000
main -הזכרון של ה
changeTo4byVal(num);
cout << "after changeTo4byVal: num = " << num << endl;
changeTo4byRef(num);
cout << "after changeTo4byRef: num = " << num << endl;
{
© Keren Kalif
19
20.
swap הדוגמא#include <iostream>
using namespace std;
void swap(int& a, int& b)
{
int temp = a;
a = b;
b = temp;
{
void main()
}
int x=3, y=5;
int: a
???
int: b
???
int: temp
???
3
2000
swap -הזכרון של ה
int: x
???
3
5
1000
int: y
???
5
3
1004
main -הזכרון של ה
cout << "Before swap: x = " << x << ", y = " << y << "\n";
swap(x, y);
cout << "After swap: x = " << x << ", y = " << y << "\n";
{
© Keren Kalif
20
21.
reference משתנה מטיפוסמתן שם נוסף למשתנה כלשהו
חייב להיות מאותחל
לא ניתן לייצר מערך של הפניות
ולכן כתובתו כמו כתובת המשתנה אליו,אינו תופס מקום נוסף
void main()
הוא מפנה
{
int x = 5, y = 3;
int& ref = x;
int: x
???
5
6
3
4
1000
int: y
???
3
1004
int&: ref
cout << &ref << " " << &x << endl;
cout << "x=" << x << ", y=" << y << ", ref=" << ref << endl;
x++;
cout << "x=" << x << ", y=" << y << ", ref=" << ref << endl;
ref = y;
cout << "x=" << x << ", y=" << y << ", ref=" << ref << endl;
ref++;
cout << "x=" << x << ", y=" << y << ", ref=" << ref << endl;
}
main -הזכרון של ה
© Keren Kalif
21
22.
החזרת טיפוס התייחסות מפונקציה בשפת Cיכולנו להחזיר כתובת של משתנה מתוך פונקציה ,וכך
למעשה החזרנו את המשתנה המקורי ,ולא העתק שלו
בשפת ++Cעדיין ניתן להחזיר משתנה ,by pointerאך ניתן גם
להחזיר משתנה by reference
יש לשים לב שכשמחזירים משתנה by referenceשהוא עדיין
יהיה קיים ביציאה מהפונקציה (בדיוק כמו בשפת )C
22
© Keren Kalif
23.
23© Keren Kalif
מפונקציהby ref דוגמא להחזרת משתנה
#include <iostream>
using namespace std;
void printArr(int arr[], int size)
{
for (int i=0 ; i < size ; i++)
cout << arr[i] << " ";
cout << endl;
{
void main()
}
int arr[] = {6,8,2};
int size = sizeof(arr)/sizeof(arr[0]);
getMax(arr, size) *= 10;
cout << "arr after changing max:\n ";
printArr(arr, size);
{
int[]: arr
הפונקציה מחזירה הפניה לאיבר המקסימלי
int& getMax(int arr[], int size)
}
int maxIndex = 0;
for (int i=1 ; i < size ; i++)
if (arr[i] > arr[maxIndex])
maxIndex = i;
return arr[maxIndex];
{
int: size
???
6
1000
???
80
8
1004
???
2
1008
???
3
1012
main -הזכרון של ה
int[]: arr
1000
1000
int: size
3
1004
???
1
1012
getMax -הזכרון של ה
int: maxIndex
24.
מרחבי שמות )(namespace
כאשר עובדים על פרויקט גדול ,לרוב משתמשים בקוד מוכן ,וכל
מתכנת כותב את חלקו
יתכן מצב שיהיו 2פונקציות בעלות שם זהה המקבלות את אותם
נתונים
תיוצר בעיה של התנגשות בשמות ,הקומפיילר לא ידע לאיזה
פונקציה לפנות
הפתרון :שימוש בnamespace -
השימוש ב namespace -מאפשר קישור של פונקציה מסוימת
לחבילת קוד מסוימת
24
© Keren Kalif
25.
1.2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
#include <iostream>
using namespace std;
:דוגמא
namespace -שימוש ב
3 להלן קטע קוד עם
namespace first
פונקציות זהות
{
void foo() }cout << "This is the first foo\n“; { מימושים נמצאים בתוך2
{
שונהnamespace
namespace second
פניה לפונקציה הנמצאת
}
namespace בתוך
void foo() }cout << "This is the second foo\n“; {
-מחייבת ציון שם ה
{
שבתוכוnamespace
void foo() }cout << "This is just foo\n“; {
היא נמצאת
void main()
פונקציה שלא בתוך
{
first::foo();
נמצאתnapespace
second::foo();
במרחב השמות הגלובלי
foo();
{
© Keren Kalif
25
26.
namespace -קיצור אופן השימוש ב1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
#include <iostream>
using namespace std;
namespace first
{
void foo() {cout << "This is the first foo\n";}
}
namespace second
}
void foo() {cout << "This is the second foo\n";}
{
using namespace second;
void main()
}
first::foo();
second::foo();
foo();
{
פקודה זו מאפשרת לנו לפנות לפונקציות
זה בלי הקידומתnamespace שתחת
© Keren Kalif
26
27.
1.2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
קיצור אופן השימוש
namespace -ב
#include <iostream>
using namespace std;
namespace first
{
void foo() {cout << "This is the first foo\n";}
}
namespace second
}
void foo() {cout << "This is the second foo\n";}
{
void foo()
}cout << "This is just foo\n“; {
using namespace first;
using namespace second;
void main()
}
first::foo();
second::foo();
foo(); // ERROR!
::foo();
{
במקרה זה נהייה חייבים תמיד לפנות
אחרת נקבל,בשם המלא של הפונקציה
ambiguous call to :את השגיאה
מאחר והקומפיילרoverloaded function
לפנות
פונקציהלפנות
לאיזו פונקציה
יודע איזו
אינו יודע
אינו
פניה בשם המלא לפונקציה
הנמצאת במרחב השמות הגלובלי
© Keren Kalif
27
28.
?using namespace std מדוע שמים את זה יש את כל הפקודות הבסיסיותnamespace בתוך
לכל הפונקציות::std בלעדיו נצטרך להוסיף את הקידומת
: אחרת נקבל למשל את השגיאה,הבסיסיות שבהן נשתמש
error C2065: 'cout' : undeclared identifier
#include <iostream>
using namespace std;
#include <iostream>
void main()
{
int x;
void main()
{
int x;
cout << "Enter a number: ";
cin >> x;
{
std::cout << "Enter a number: ";
std::cin >> x;
{
© Keren Kalif
28
29.
:ביחידה זו למדנו הגדרת תכנות מכוון עצמים
:++C - לC השוני הסינטקטי בין
printf cout
scanf cin
gets cin.getline
malloc new
free delete
טיפוס התייחסות
)namespace( מרחבי שמות
© Keren Kalif
29
30.
תרגול© Keren Kalif
30