תכנות מכוון עצמים ו- C++ יחידה 03 מחלקות: תכונות, שיטות, הרשאות, const

Slides:



Advertisements
Similar presentations
Operator overloading redefine the operations of operators
Advertisements

Approfondimento Classi - Esempi1 // Argomento: Oggetti membri di altre classi // Declaration of the Date class. // Member functions defined in date1.cpp.
Esempio Polimorfismo1 // Definition of abstract base class Shape #ifndef SHAPE_H #define SHAPE_H class Shape { public: virtual double area() const { return.
What is the out put #include using namespace std; void main() { int i; for(i=1;i
Classi - Esempi1 // SalesPerson class definition // Member functions defined in salesp.cpp #ifndef SALESP_H #define SALESP_H class SalesPerson { public:
Prof. amr Goneid, AUC1 CSCE 110 PROGRAMMING FUNDAMENTALS WITH C++ Prof. Amr Goneid AUC Part 14. User Defined Classes.
1 CSE 2341 Object Oriented Programming with C++ Note Set #6.
Prof. Amr Goneid, AUC1 CSCE 210 Data Structures and Algorithms Prof. Amr Goneid AUC Part R1. ADTs as Classes.
 2000 Deitel & Associates, Inc. All rights reserved. Optional Case Study - Chapter 7 Outline 7.1 Introduction 7.2 Overview of Simulation Implementation.
C ++ Programming Languages Omid Jafarinezhad Lecturer: Omid Jafarinezhad Fall 2013 Lecture 2 Department of Computer Engineering 1.
CHAPTER 13 CLASSES AND DATA ABSTRACTION. In this chapter, you will:  Learn about classes  Learn about private, protected, and public members of a class.
Current Assignments Homework 3 is due tonight. Iteration and basic functions. Exam 1 on Monday.
Object-Oriented Programming. Procedural Programming All algorithms in a program are performed with functions and data can be viewed and changed directly.
11 Introduction to Object Oriented Programming (Continued) Cats.
CSC1201: Programming Language 2 Lecture 1 Level 2 Course Nouf Aljaffan (C) CSC 1201 Course at KSU1.
Variables and Data Types.  Variable: Portion of memory for storing a determined value.  Could be numerical, could be character or sequence of characters.
Chapter 11 Separate Compilation and Namespaces. Learning Objectives Separate Compilation –Encapsulation reviewed –Header and implementation files Namespaces.
W 4 L 1 sh 1 LessonSubjectBook Week 4 lesson 1Class, copy-constructorH ; p197 – 226 Week 4 lesson 2Operators 1H ; p237 – 254 Week 5 lesson.
Input a number #include using namespace std; int main() { int num; cout num; return 0; }
CS Introduction to Data Structures Spring Term 2004 Franz Hiergeist.
Classes and Objects CS177 Rec 10. Announcements Project 4 is posted ◦ Milestone due on Nov. 12. ◦ Final submission due on Nov. 19. Exam 2 on Nov. 4 ◦
1 More Operator Overloading Chapter Objectives You will be able to: Define and use an overloaded operator to output objects of your own classes.
Prof. amr Goneid, AUC1 CSCE 110 PROGRAMMING FUNDAMENTALS WITH C++ Prof. Amr Goneid AUC Part 15. Dictionaries (1): A Key Table Class.
11 Introduction to Object Oriented Programming (Continued) Cats.
1 CSC 1111 Introduction to Computing using C++ C++ Basics (Part 1)
Chapter 2 Creating a C++ Program. Elements of a C++ Program Four basic ways of structuring a program Four basic ways of structuring a program 1.Sequencing.
Exercises on Polymorphism and Operator Overloading TCP1201: 8.
1 Compiler directive: #define, usage 1 #include using namespace std; #define TAX //double TAX=0.08; #define LAST_NAME "Li" #define FIRST_NAME "Dennis"
 2000 Deitel & Associates, Inc. All rights reserved. Optional Case Study - Chapter 6 Outline 6.1 Introduction 6.2 Implementation: Visibility 6.3 Implementation:
Chapter five exercises. a. false; b. true; c. false; d. true; e. true; f. true; g. true; h. false.
משפטי תנאי ( לוגיקה ) קרן כליף. 2 © Keren Kalif ביחידה זו נלמד :  משפטי תנאי  משפט switch  משפט if מקוצר.
Nested Structures struct TDate { int year, month, day; }; struct StudentType { string id, firstName, lastName; float gpa; TDate DOB; }; struct SectionType.
1 C++ Classes and Data Structures Course link…..
C++ Lesson 1.
Chapter 1.2 Introduction to C++ Programming
A CLASS CONSISTS OF VARIABLES,
CSCE 210 Data Structures and Algorithms
Chapter 1.2 Introduction to C++ Programming
#define #include<iostream> using namespace std; #define GO
Classes and Data Abstraction
Template Classes and Functions
Section 3 Review Mr. Crone.
CMPE Data Structures and Algorithms in C++ February 22 Class Meeting
مبانی کامپیوتر و برنامه سازی
לולאות קרן כליף.
Reserved Words.
הקצאות דינאמיות בשילוב מבנים
Dynamic Memory Allocation Reference Variables
Andy Wang Object Oriented Programming in C++ COP 3330
בניית מחלקות.
פונקציות לעיתים קרובות לא נוח להגדיר את כל התוכנה בתוך גוף אחד.
בנאים (constructor) ו- this
אבני היסוד של תוכנית ב- C++
אבני היסוד של תוכנית ב- C++
Screen output // Definition and use of variables
תכנות מכוון עצמים ו- C++ יחידה 06 העמסת אופרטורים
תכנות מכוון עצמים ו- C++ יחידה 01 מ- C ל- C++
הרצאה 03 אבני היסוד של תוכנית ב- C
בניית מחלקות.
Starting Out with C++: From Control Structures through Objects
Pointers & Functions.
C++ File Structure and Intro to the STL
Classes.
CS1201: Programming Language 2
foo.h #ifndef _FOO #define _FOO template <class T> class foo{
C++ File Structure and Intro to the STL
Pointers & Functions.
(Dreaded) Quiz 2 Next Monday.
Class StudentList class StudentList { private: int numStudents;
Andy Wang Object Oriented Programming in C++ COP 3330
Presentation transcript:

תכנות מכוון עצמים ו- C++ יחידה 03 מחלקות: תכונות, שיטות, הרשאות, const קרן כליף

ביחידה זו נלמד: מהי מחלקה פניה אל תכונות ושיטות המחלקה הרשאות גישה מחלקה המכילה מחלקה אחרת העברת פרמטר by ref בעיית ה- include הכפולים פרמטר const שיטת const ערך מוחזר const משתנה const constexpr מתודות inline

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

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

לאובייקטים יש מאפיינים נתכנן תוכנה לניהול נתוני הסרט אחד מהאובייקטים יהיה השחקנית ג'וליה רוברטס: שם: ג'וליה רוברטס תאריך לידה: 28/10/1967 סרט מפורסם: "אישה יפה" מספר פרסים: 50

אובייקטים יכולים לעשות דברים - שיטות שיטות ש"ג'וליה רוברטס" יודעת לעשות: לככב במדורי רכילות להיות מועמדת לפרס להצטלם על השטיח האדום

האובייקט ג'וליה רוברטס - סיכום תכונות של האובייקט ג'וליה רוברטס: להיות מועמדת לאוסקר להצטלם על השטיח האדום לככב במדורי רכילות שם: ג'וליה רוברטס תאריך לידה: 28/10/1967 סרט מפורסם: "אישה יפה" מספר פרסים: 50 פעולות ג'וליה רוברטס יכולה לבצע:

אובייקטים נוספים דומים שם: רוברט רדפורד תאריך לידה: 18/08/1936 סרט מפורסם: "הצעה מגונה" מספר פרסים: 33 שם: בראד פיט תאריך לידה: 18/12/1963 סרט מפורסם: "מר וגברת סמית" מספר פרסים: 63 להיות מועמדת לאוסקר להצטלם על השטיח האדום לככב במדורי רכילות כל אחד מהם יכול גם-כן לבצע את השיטות:

יש כאן מבנה יש מספר אובייקטים מאותו טיפוס (שחקן), בעלי תכונות זהות, אבל עם ערכים שונים אב טיפוס זה נקרא מחלקה (class) בדוגמא זו נקרא למחלקה בשם Actor שימו לב: כל שחקן הוא שונה אבל הם כולם אובייקטים (מופעים) של המחלקה Actor שם: בראד פיט תאריך לידה: 18/12/1963 סרט מפורסם: "מר וגברת סמית" מספר פרסים: 63 שם: רוברט רדפורד תאריך לידה: 18/08/1936 סרט מפורסם: "הצעה מגונה" מספר פרסים: 33

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

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

מחלקות (classes) לעומת אובייקטים מופעים של המחלקה Player 2: Attributes: Name = בראד פיט Birth Date = 18/12/1963 Famous movie = מר וגברת סמית Wins = 63 Methods: BeNominated WalkOnRedCarpet BeGossiped אובייקט Actor Attributes: Name Birth Date Famous movie Wins Methods: BeNominated WalkOnRedCarpet BeGossiped מחלקה (class) Player 1: Attributes: Name = רוברט רדפורד Birth Date = 18/03/1936 Famous movie = הצעה מגונה Wins = 33 Methods: BeNominated WalkOnRedCarpet BeGossiped אובייקט

מחלקות (classes) – שימו לב מחלקה היא דרך מופשטת לתיאור של כל העצמים (אובייקטים) מאותו סוג עד שלא יצרנו אובייקט של המחלקה, יש לנו רק תיאור מופשט (אבטיפוס) Actor Attributes: Name Birth Date Famous movie Wins Methods: BeNominated WalkOnRedCarpet BeGossiped מחלקה (class)

שאלה הכיסא שאתם יושבים עליו, האם הוא מחלקה או אובייקט? והלוח? זכרו: מחלקה היא רק תאור מופשט!

מהן תכונות ומהן שיטות ב- OOP תכונה (attribute) היא משתנה המשויך לאובייקט מסוים התכונה יכולה להיות מכל טיפוס שלמדנו עד כה (וטיפוסים נוספים) שיטה (method) היא פונקציה, אך משויכת לאובייקט שם השיטה מעיד "מה" השיטה עושה אוסף הפעולות בשיטה מעיד על ה"איך" השיטה עושה זאת למחלקות שונות יתכנו תכונות ושיטות עם שמות זהים למשל, גם למחלקה "שחקן כדורסל" וגם למחלקה "ליצן" יכולה להיות התכונה name, ולשתיהן יכולה להיות השיטה show

OOP בשפת C++ כאשר נכתוב מחלקה נייצר 2 קבצים: קובץ עם סיומת h שיכיל את ה"מה" של המחלקה: מה שמה מה תכונותיה מה הפעולות (שיטות, methods) קובץ עם סיומת cpp שיכיל את ה"איך" של המחלקה": מימוש הפעולות ניתן לכתוב את המימושים בקובץ ה- h, אך נעדיף להשאירו "נקי" עם תיאורי ה"מה" בלבד

דוגמה | המחלקה Clock clock.cpp clock.h נשים לב שזוהי רק הגדרת המחלקה, עדיין לא יצרנו משתנה! יש לעשות include לקובץ ה- h של המחלקה #include <iostream> using namespace std; #include "clock.h" void Clock::show() { cout << (hours < 10 ? "0" : "") << hours << ":" << (minutes < 10 ? "0" : "") << minutes; } void Clock::tick() addMinutes(1); void Clock::addMinutes(int add) minutes += add; hours += minutes / 60; minutes %= 60; hours %= 24; clock.cpp במימוש יש לשייך את השיטה למחלקה, ע"י ציון: <class name>:: המילה class שמורה בשפה ומעידה שפה תהייה הגדרה של מחלקה #ifndef __CLOCK_H #define __CLOCK_H class Clock { public: int hours, minutes; void show(); void tick(); void addMinutes(int add); }; #endif // __CLOCK_H clock.h שם המחלקה נסביר בהמשך... תכונות המחלקה שיטות המחלקה לא לשכוח ; בסוף המחלקה

דוגמה | המחלקה Clock | שימוש ב- main #include <iostream> using namespace std; #include "clock.h" void main() { Clock c; c.show(); cout << endl; c.hours = 22; c.minutes = 15; c.addMinutes(65); } כדי לפנות לתכונה או לשיטה של האובייקט נשתמש ב- "." לאובייקט המפעיל שיטה נקרא "אוביקט מפעיל" שם הטיפוס שם המשתנה קריאה לשיטה של האובייקט מתן ערכים לשדות האובייקט קריאה לשיטה של האובייקט המקבלת פרמטרים 0-858993460:0-858993460 22:15 23:20

יצירת כמה אובייקטים מאותה מחלקה #include <iostream> using namespace std; #include "clock.h" void main() { Clock c1, c2; c1.hours = 22; c1.minutes = 15; c2.hours = 14; c2.minutes = 45; cout << "Clock 1: "; c1.show(); cout << endl; cout << "Clock 2: "; c2.show(); } © Keren Kalif Clock 1: 22:15 Clock 2: 14:45 כאשר פונים לשיטה של אובייקט, האובייקט מכיר את ערכי תכונותיו שלו בלבד

בדיוק כמו עבודה עם מערך של מבנים.. יצירת מערך של Clock #include <iostream> using namespace std; #include "clock.h" void main() { Clock myClocks[2]; myClocks[0].hours = 22; myClocks[0].minutes = 15; myClocks[1].hours = 14; myClocks[1].minutes = 45; cout << "Clock 1: "; myClocks[0].show(); cout << endl; cout << "Clock 2: "; myClocks[1].show(); } בדיוק כמו עבודה עם מערך של מבנים.. Clock 1: 22:15 Clock 2: 14:45 © Keren Kalif

הקצאה דינאמית של Clock הקצאה דינאמית של מערך #include <iostream> using namespace std; #include "clock.h" void main() { Clock* c = new Clock[2]; c[0].hours = 22; c[0].minutes = 30; c[1].hours = 20; c[1].minutes = 45; for (int i = 0; i < 2; i++) c[i].show(); cout << endl; } delete []c; הקצאה דינאמית של מערך #include <iostream> using namespace std; #include "clock.h" void main() { Clock* c = new Clock; c->hours = 22; c->minutes = 15; c->show(); cout << endl; delete c; } הקצאה דינאמית של אובייקט אחד כאשר המשתנה הוא מצביע, הפניה לשדות היא באמצעות <- שחרור המערך שחרור ההקצאה

הרשאות private ו- public לא נרצה שהתכונות שלנו יהיו חשופות ושכל אחד יוכל לשנות את ערכיהן ע"י השמה למשל שלא יוכלו לשים בערך של הדקות מספר שאינו בין 0 ל- 59 לכן ניתן לתת הרשאות לתכונות ולשיטות של המחלקה לתכונות המחלקה ניתן הרשאת private, משמע ניתן לגשת אליהן רק מתוך המחלקה שיטות יהיו תחת הרשאת public כדי שיהיו נגישות מחוץ למחלקה שיטות שנרצה שיהיו לשימוש פנימי של המחלקה נגדיר ב- private #ifndef __CLOCK_H #define __CLOCK_H class Clock { private: int hours, minutes; public: void show(); void tick(); void addMinutes(int add); }; #endif // __CLOCK_H clock.h הרשאת ברירת המחדל היא private, לכן לא היינו חייבים לציין אותה בהתחלה. לכן חשוב היה בדוגמאות הקודמות לכתוב את ה- public

המחלקה Clock - השינוי בקוד עם שינוי ההרשאה נקבל שגיאת קומפילציה: #include <iostream> using namespace std; #include "clock.h" void main1() { Clock c; c.hours = 22; c.minutes = 15; c.show(); cout << endl; }

הפתרון כדי לאפשר השמת ערך בתכונות שהן private, נכתוב שיטות שהן public המבצעות את פעולת ההשמה נרצה לכתוב שיטה המקבלת כנתון את הערך המבוקש, השיטה תבצע את בדיקות התקינות על ערך זה ולבסוף תשים אותו בתכונה נרצה לכתוב שיטה המחזירה את ערך התכונה נהוג לקרוא לשיטות אלו setter'ים ו- getter'ים © Keren Kalif

מימוש שיטות set ו- get תפקיד שיטת get להחזיר ערך של תכונה באובייקט #include <iostream> using namespace std; #include "clock.h" int Clock::getMinutes() { return minutes; } int Clock::getHours() return hours; void Clock::setMinutes(int m) minutes = m; void Clock::setHours(int h) hours = h; void Clock::show() {...} void Clock::tick() {...} void Clock::addMinutes(int add) {...} מימוש שיטות set ו- get #ifndef __CLOCK_H #define __CLOCK_H class Clock { private: int hours, minutes; public: int getMinutes(); int getHours(); void setMinutes(int m); void setHours(int h); void show(); void tick(); void addMinutes(int add); }; #endif // __CLOCK_H תפקיד שיטת get להחזיר ערך של תכונה באובייקט תפקיד שיטת set לשים ערך בתוך תכונה באובייקט נשים לב שעדיין ניתן לשים ערכים לא תקינים בתכונות האובייקט. יטופל בהמשך!

שימוש בשיטות להשמה ולקבלת ערכים #include <iostream> using namespace std; #include "clock.h" void main() { Clock c; c.show(); cout << endl; c.setHours(8); c.setMinutes(20); cout << "The hour is around " << c.getHours() << endl; } 0-858993460:0-858993460 08:20 The hour is around 8

setter'ים ו- getter'ים – מימושים מתוקנים #include "clock.h" int Clock::getMinutes() {...} int Clock::getHours() {...} void Clock::setMinutes(int m) { if (m < 0 || m >= 60) cout << "Minutes have to be between 0-59. Value is unchanged.\n"; else minutes = m; } void Clock::setHours(int h) if (h < 0 || h >= 24) cout << "Hours have to be between 0-23. Value is unchanged.\n"; hours = h; void Clock::show() {...} void Clock::tick() {...} void Clock::addMinutes(int add) {...} בתוך ה- setter'ים באה לידי ביטוי העבודה שהתכונות הן private: לא ניתן לשנות אותן ללא בקרה

תוצר ההרצה לאחר התיקון 0-858993460:0-858993460 08:20 #include <iostream> using namespace std; #include "clock.h" void main() { Clock c; c.show(); cout << endl; c.setHours(8); c.setMinutes(20); c.setHours(25); c.setMinutes(30); } תוצר ההרצה לאחר התיקון 0-858993460:0-858993460 08:20 Hours have to be between 0-23. Value is unchanged. 08:30

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

השיטות set: עדכון #ifndef __CLOCK_H #define __CLOCK_H class Clock { bool Clock::setMinutes(int m) { if (m < 0 || m >= 60) cout << "Minutes … unchanged.\n"; return false; } else minutes = m; return true; #ifndef __CLOCK_H #define __CLOCK_H class Clock { private: int hours, minutes; public: int getMinutes(); int getHours(); bool setMinutes(int m); bool setHours(int h); void show(); void tick(); void addMinutes(int add); }; #endif // __CLOCK_H bool Clock::setHours(int h) { if (h < 0 || h >= 24) cout << "Hours … unchanged.\n"; return false; } else hours = h; return true;

שימוש בשיטות ה- set ב- main Enter hours: 30 Hours have to be between 0-23. Value is unchanged. Enter hours: 20 Enter minutes: 100 Minutes have to be between 0-59. Value is unchanged. Enter minutes: 30 20:30 void main() { Clock c; bool res; int hours, minutes; do { cout << "Enter hours: "; cin >> hours; res = c.setHours(hours); } while (res != true); cout << "Enter minutes: "; cin >> minutes; res = c.setMinutes(minutes); c.show(); cout << endl; }

סיכום set'ים ו- get'ים כדי לאפשר השמת ערך בתכונה שהיא private, נכתוב שיטת set, שהיא public, המבצעת את פעולת ההשמה: השיטה תקבל כנתון את הערך המבוקש השיטה תבצע את בדיקות התקינות על ערך שהתקבל לבסוף השיטה תעדכן את הערך המתאים בתכונה כדי לאפשר קבלת ערך תכונה שהיא private, נכתוב שיטת get שהיא public נהוג לקרוא לשיטות אלו setter'ים ו- getter'ים

class לעומת struct על-מנת להגדיר טיפוס חדש: ההבדל ביניהם הוא בהרשאה: בשפת C משתמשים ב- struct בשפת C++ משתמשים ב- class ההבדל ביניהם הוא בהרשאה: הרשאת ברירת המחדל ב- struct היא public ולכן יכולנו לפנות לשדותיו באופן ישיר הרשאת ברירת המחדל ב- class היא private ניתן לכתוב גם מתודות ב- struct אך זהו כבר ממש תכנות מונחה עצמים ולכן מקובל להשתמש ב- class

האם תמיד התכונות יהיו ב- private? ישנם מקרים בהם אין צורך בבדיקות תקינות עבור הערכי התכונות למשל, עבור המחלקה Person המייצגת אדם, שתכונותיה הם שם ו- ת.ז., כאשר אין כרגע צורך בהגבלות תקינות #ifndef __PERSON_H #define __PERSON_H class Person { public: char name[20]; int id; }; #endif // __PERSON_H #include <iostream> using namespace std; #include "person.h" void main() { Person p; strcpy(p.name, "gogo"); p.id = 111; }

האם תמיד התכונות יהיו ב- private? (2) אבל אם פתאום נחליט שמספר ת.ז. חייב להיות 9 ספרות, נצטרך לעדכן את המחלקה, וה- main כבר לא יתקמפל! bool Person::setId(int i) { int counter = 0; while (i > 0) i /= 10; counter++; } if (counter == 9) id = i; return true; else return false; #ifndef __PERSON_H #define __PERSON_H class Person { public: char name[20]; private: int id; int getId(); bool setId(int i); }; #endif // __PERSON_H void main() { Person p; strcpy(p.name, "gogo"); p.id = 111; } int Person::getId() { return id; }

תכונות תמיד יהיו private! אפילו אם בעת כתיבת המחלקה אין הגבלות תקינות על תכונה, תמיד נשים אותה עם הרשאת private ונספק מתודות set ו- get 2 סיבות מרכזיות לאופן כתיבה זה: שאם בעתיד תתווסף בדיקת תקינות, מי שמשתמש במחלקה לא יצטרך לשנות את הקוד שלו, שכן כבר מראש הוא ישתמש במתודת ה- set, וכל שינוי בתוך גוף המתודה יהיה שקוף מבחינתו אחידות, כך שהפניה לכל התכונות במחלקה תהייה באופן זהה, באמצעות שיטות set או get

אתחול תכונות שהן private בהמשך נראה כיצד ניתן לתת ערכים לתכונות האובייקט עם אתחולו כרגע עם יצירת האובייקט כל ערכי שדותיו הם זבל נקפיד שתכונות האובייקט יהיו private!

זוהי גם העמסת שיטות, שכן עכשיו ניתן לקרוא לשיטות אלו ב- 2 אופנים ערכי default לפרמטרים #ifndef __CLOCK_H #define __CLOCK_H class Clock { private: int hours, minutes; public: int getMinutes(); int getHours(); bool setMinutes(int m=0); bool setHours (int h=0); void show(); void tick(); void addMinutes(int add); }; #endif // __CLOCK_H clock.h #include <iostream> using namespace std; #include "clock.h" void main() { Clock c; c.show(); cout << endl; c.setHours(5); c.setMinutes(); } זוהי גם העמסת שיטות, שכן עכשיו ניתן לקרוא לשיטות אלו ב- 2 אופנים 0-858993460:0-858993460 05:00

נגדיר את ה- enum ב- public כדי שיהיה נגיש גם מחוץ למחלקה class Clock { public: enum eDisplayType {FULL_DAY, HALF_DAY}; int getMinutes(); int getHours(); eDisplayType getDisplayType(); bool setMinutes(int m=0); bool setHours(int h=0); void setDisplayType(eDisplayType type); void show(); void tick(); void addMinutes(int add); private: int hours, minutes; eDisplayType displayType; }; נגדיר את ה- enum ב- public כדי שיהיה נגיש גם מחוץ למחלקה void Clock::show() { int h = hours; if (displayType == HALF_DAY) h %= 12; cout << (h < 10 ? "0" : "") << h << ":" << (minutes < 10 ? "0" : "") << minutes; cout << (hours < 12 ? "am" : "pm"); } ה- private עבר לסוף הקובץ משום שיש בו שימוש ב- enum, שצריך להיות מוגדר מעליו

שימוש ב- enum במחלקה: ה- main void main() { Clock c; c.setHours(22); c.setMinutes(30); c.setDisplayType(Clock::FULL_DAY); cout << "The time is (full day): "; c.show(); cout << endl; c.setDisplayType(Clock::HALF_DAY); cout << "The time is (half day): "; } ה- enum הוא קבוע המוגדר בחלק ה- public במחלקה, לכן ניתן לגשת אליו בשמו המלא מחוץ למחלקה The time is (full day): 22:30 The time is (half day): 10:30pm

מחלקה המכילה מחלקה #ifndef __OVEN_H #define __OVEN_H #include "clock.h" class Oven { private: int temperature; Clock startTime; int minutesToWork; public: void show(); int getTemperature(); Clock getStartTime(); int getMinutesToWork(); void setTemperature(int t); void setStarTime(Clock c); void setMinutesToWork(int t); }; #endif // __OVEN_H void Oven::show() { cout << "Temperature: " << temperature << "\nMinutes: " << minutesToWork << "\nStart working at "; startTime.show(); cout << endl; }

מחלקה המכילה מחלקה: ה- main #include <iostream> using namespace std; #include "clock.h" #include "oven.h" void main() { Oven o; Clock c; c.setHours(13); c.setMinutes(); o.setTemperature(180); o.setMinutesToWork(50); o.setStarTime(c); o.show(); } Temperature: 180 Minutes: 50 Start working at 13:00

תזכורת: בעיית ה- include הכפולים #include <iostream> using namespace std; #include "clock.h" #include "oven.h" void main() { Oven o; Clock c; c.setHours(13); c.setMinutes(); o.setTemperature(180); o.setMinutesToWork(50); o.setStarTime(c); o.show(); } במידה והקובץ clock.h לא היה עטוף ב- ifndef היינו מקבלים שגיאת קומפילציה של redefinition

שדרוג המחלקה Oven #ifndef __OVEN_H #define __OVEN_H #include "clock.h" class Oven { private: int temperature; Clock startTime; int minutesToWork; public: void show(); int getTemperature(); Clock& getStartTime(); int getMinutesToWork(); void setTemperature(int t); void setStarTime(Clock& c); void setMinutesToWork(int t); }; #endif // __OVEN_H פרמטרים מטיפוס אובייקט תמיד ישלחו by ref מטעמי יעילות, אין שינוי במימוש. ערך מוחזר המחזיר תכונה של האובייקט שהינה אובייקט בעצמה, גם תחזור by ref מטעמי יעילות, כדי לחסוך את ההעתקה מטעמי יעילות, כדי לא לשלוח העתק של האובייקט לפונקציה ומהפונקציה, נקבל ונשלח רק reference אליו. מקביל לשליחת מצביע ב- C

הבעייתיות בהעברת פרמטר by ref הבעיה: האובייקט המקורי חשוף לשינויים בתוך הפונקציה הפתרון: הצהרה שהפונקציה אינה משנה את הפרמטר סינטקס: שמים את המילה const לפני טיפוס הפרמטר: void foo(const MyClass& c) המשתנה יהיה קבוע בתוך הפונקציה, ולא ניתן יהיה לשנותו

הגנה על הפרמטר מפני שינויים בתוך הפונקציה: העברת פרמטר כ- const #ifndef __OVEN_H #define __OVEN_H #include "clock.h" class Oven { private: int temperature; Clock startTime; int minutesToWork; public: void show(); int getTemperature(); Clock& getStartTime(); int getMinutesToWork(); void setTemperature(int t); void setStarTime(const Clock& c); void setMinutesToWork(int t); }; #endif // __OVEN_H כאשר מעבירים פרמטר לפונקציה שהוא אובייקט תמיד נעביר אותו by ref מטעמי יעילות, ונציין שהוא const, כדי שיהיה ברור לקורא הקוד שהפרמטר הועבר by ref מטעמי יעילות, ולא על-מנת לשנותו הגנה על הפרמטר מפני שינויים בתוך הפונקציה: מועבר by ref מטעמי יעילות – לחסוך את ההעתקה, ולכן ישנו ה- const כדי ליידע את הקורא שמשתנה זה אינו ניתן לשינוי בפונקציה

משתנים/פרמטרים שהם const void main() { Clock c1; c1.show(); const Clock c2; c2.show(); }

כאשר שיטה אינה משנה את ערכי תכונות האובייקט, נצהיר עליה כ- const class Clock { public: enum eDisplayType {FULL_DAY, HALF_DAY}; int getMinutes() const; int getHours() const; eDisplayType getDisplayType() const; bool setMinutes(int m=0); bool setHours(int h=0); void setDisplayType(eDisplayType type); void show() const; void tick(); void addMinutes(int add); private: int hours, minutes; eDisplayType displayType; }; שימו לב: הקומפיילר אינו מתריע על אי הגדרת const, אך זהו תכנות נכון, מעין "חוזה" בין מי שכותב את המחלקה למי שמשתמש בה, ולכן יש להקפיד על שימוש נכון ב- const

const הוא חלק מחתימת השיטה 2 שיטות בעלות שם זהה ורשימת פרמטרים זהה, יכולות להיבדל אחת מהשניה ב- const (functions overloading): במקרה זה, כאשר יש משתנה רגיל ומשתנה const כל אחד יפנה לשיטה המתאימה

שאלה האם ניתן היה לוותר על אחת מ- 2 הגרסאות? כן, הגרסא בלי ה- const משתנה שהוא const יכול להפעיל אך ורק שיטה שהיא const משתנה רגיל יכול להפעיל כל שיטה

האם הקוד הבא מתקמפל? אם כן, מה הפלט, אחרת מהי השגיאה? התיקון יהיה להגדיר את השיטה foo כ- const הקוד אינו מתקמפל מאחר ו- getInner מחזירה אובייקט שהוא const ולכן ניתן להפעיל עליו רק שיטות שהוגדרו כ- const

פונקציית constexpr ידוע לנו כי ערך החוזר פונקציה מחושב בזמן ריצה במידה וכל הערכים שבשימוש הפונקציה ידועים בזמן קומפילציה, ניתן לגרום לפונקציה לחשב את הערך המוחזר כבר בזמן קומפילציה ובכך לחסוך בביצועים בזמן ריצה constexpr double getCircleArea(int radius) { return 3.14 * radius * radius; } void main() const int RADIUS = 5; cout << "circle area with radius=" << RADIUS << " is " << getCircleArea(RADIUS) << endl; int radius; cout << "Enter radius: "; cin >> radius; cout << "circle area with radius=" << radius << " is " << getCircleArea(radius) << endl; מאחר ו- r1 הוא const, הקומפיילר מחשב את הערך המוחזר מהפונקציה כבר בזמן קומפילציה מאחר וערכו של r2 ידוע רק בזמן ריצה, הפונקציה מתנהגת רגיל ומחושבת בזמן ריצה

פונקציות constexpr כאשר הקומפיילר מתייחס להגדרת ה- constexpr הפונקציה הופכת להיות inline מתודות המוגדרות כ- constexpr אינן יכולות להיות וירטואליות (רלוונטי לפרק של פולימורפיזם) ישנה הגבלה ל- return יחיד במימוש, אחרת תהיה שגיאת קומפילציה

כיצד ניתן לדעת שהקומפיילר אכן משתמש בפונקציה כ- constexpr? constexpr double getCircleArea(int radius) { return 3.14 * radius * radius; } void main() const int RADIUS = 5; cout << "circle area with radius=" << RADIUS << " is " << getCircleArea(RADIUS ) << endl; static_assert(getCircleArea(RADIUS ) == (3.14 * 25) , "result should be 3.14*5*5"); int radius; cout << "Enter radius: "; cin >> radius; cout << "circle area with radius=" << radius << " is " << getCircleArea(radius) << endl; static_assert(getCircleArea(radius) == (3.14 * 25), static_assert משמש לבדיקת ערך הידוע בזמן קומפילציה. במידה והערך אינו ידוע, תוצג שגיאה בזמן קומפילציה.

משתנה constexpr לעומת משתנה const void main() { int x; cin >> x; const int y1 = x + 5; constexpr int y2 = x + 5; }

מתודות inline כאשר כותבים מתודה במחלקה, הקפיצה אליה מתבצעת בזמן ריצה (זהו המנגנון הרגיל של קריאה לפונקציות) קריאות מרובות למתודה יכולות לייצר תקורה בזמן ריצת התוכנית תקורה זו די מינימלית, אבל יש מערכות בהן כל חלקיק שניה משמעותי הגדרת המתודה כ- inline תדאג למנוע את הקפיצה למתודה ע"י שתילת קוד המתודה במקום המבוקש (הרעיון כמו macro) ציון כי מתודה היא inline הינה המלצה בלבד לקומפיילר: הקומפיילר יכול להתעלם ממנה הקומפיילר יכול להחליט על מתודה מסויימת שהיא inline גם אם המתכנת לא הצהיר על כך במפורש

מתודת inline: דוגמה class Stam { private: int x; public: Stam(int num) x = num; } inline int getX() const; }; int Stam::getX() const return x; המימוש של פונקציית inline צריך להיות זמין בזמן הקומפילציה, ולכן ימומש בקובץ ה- h int getX() const {return x;} מתודות שממומשת ב- header הינן עם המלצת inline באופן אוטומטי. פונקציות הכוללות לולאות לא יהיו inline.

ביחידה זו למדנו: מהי מחלקה פניה אל תכונות ושיטות המחלקה הרשאות גישה מחלקה המכילה מחלקה אחרת העברת פרמטר by ref בעיית ה- include הכפולים פרמטר const שיטת const ערך מוחזר const משתנה const constexpr מתודות inline

תרגול (1/4) כתוב את המחלקה Survivor שנתוניה: שיטות המחלקה: שם השורד: מחרוזת סטטית בגודל 20 גיל סטטוס משפחתי (רווק/נשוי/במערכת יחסים) שיטות המחלקה: אתחול: שיטה המקבלת מחרוזת המייצגת את שם השורד, גיל, וסטטוס משפחתי ומאתחלת את נתוניו שיטה המדפיסה את נתוני השורד

תרגול (2/4) כתבו main: שאלו את המשתמש כמה שורדים יש בכל שבט הקצו דינאמית 2 מערכים של מצביעים ל- Survivor בגודל המבוקש קראו נתונים בלולאה לתוך 2 מערכי השורדים (זכרו: יש להקצות דינאמית כל איבר. מדוע?) הדפיסו את נתוני 2 המערכים שחררו זכרון

תרגול (3/4) כתבו את המחלקה Tribe שנתוניה: שיטות המחלקה: שם השבט: מחרוזת סטטית בגודל 20 מספר השורדים המקסימלי בשבט מערך של מצביעים ל- Survivor מספר השורדים שנשארו בשבט שיטות המחלקה: אתחול (תקבל שם שם השבט, ומספר השורדים המקסימלי, ותאתחל את מערך השורדים ואת מספר השורדים שנותרו בהתאם). הוספת שורד לשבט ועדכון הנתונים הרלוונטים. הדחה: תקבל שם של שורד. ותשחרר את הקצאתו מהמערך, תצמצם את הרווח שנותר ותעדכן את מספר השורדים שנותרו בשבט הדפסה שמות כל השורדים בשבט

תרגול (4/4) שנו את ה- main: ייצר 2 שבטים קרא נתונים בלולאה לתוך 2 השבטים (זכרו: יש להקצות דינאמית כל איבר) הדפיסו את השבטים הדיחו 2 שורדים הדפיסו את השבטים לאחר ההדחות שחררו זיכרון solution