Menu
Coddy logo textTech

מחלקות Enum וטיפוסיות חזקה

חלק מהיחידה תכנות מונחה עצמים במסלול ה-C++ של Coddy. שיעור 80 מתוך 104.

C++11 הציגה מחלקות enum (המכונות גם מִנְיוֹנִים תחומים) כדי להתמודד עם החסרונות של מִנְיוֹנִים מסורתיים בסגנון C. הן מספקות בטיחות טיפוסים חזקה יותר ומונעות שימוש שגוי מקרי בערכי מִנְיוֹן.

ל-enum מסורתיים יש בעיות: הערכים שלהם דולפים אל תחום השמות שמסביב ומומרים באופן מרומז למספרים שלמים, דבר שמוביל לבאגים חמקמקים:

// enum מסורתי - בעייתי
enum Color { Red, Green, Blue };
enum TrafficLight { Red, Yellow, Green };  // שגיאה! Red ו-Green כבר הוגדרו

int x = Red;  // מומר אוטומטית ל-int (0)
if (Red == 0) { }  // עובר הידור - השוואה בין enum ל-int

מחלקות enum פותרות את הבעיות האלה באמצעות תחימה של ערכים ומניעת המרות משתמעות:

enum class Color { Red, Green, Blue };
enum class TrafficLight { Red, Yellow, Green };  // תקין - אין התנגשות

Color c = Color::Red;      // חובה להשתמש באופרטור תחום
// int x = c;              // שגיאה! אין המרה מרומזת
int x = static_cast<int>(c);  // נדרשת המרה מפורשת

// if (c == 0) { }         // שגיאה! אי אפשר להשוות ל-int
if (c == Color::Red) { }   // תקין - השוואה בין ערכים מאותו סוג

אפשר גם לציין את הטיפוס הבסיסי לצורך שליטה בזיכרון:

enum class Status : uint8_t {
    Inactive = 0,
    Active = 1,
    Pending = 2
};

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

challenge icon

אתגר

קל

בואו נבנה מערכת לתעדוף משימות שמשתמשת במחלקות enum כדי לייצג רמות עדיפות שונות וסטטוסים של משימות. כך נראה כיצד מחלקות enum מספקות בטיחות טיפוסים ומונעות סוגי באגים שמתרחשים עם enums מסורתיים.

תארגנו את הקוד בשלושה קבצים:

  • TaskTypes.h: הגדירו את מחלקות ה-enum עבור מערכת המשימות.

    צרו מחלקת enum בשם Priority עם הערכים: Low, Medium, High ו-Critical. ציינו את int כטיפוס הבסיס, עם הערכים 1, 2, 3 ו-4, בהתאמה.

    צרו מחלקת enum בשם Status עם הערכים: Pending, InProgress ו-Completed.

    ספקו שתי פונקציות עזר:

    • priorityToString(Priority p): מחזירה את העדיפות כמחרוזת ("Low", "Medium", "High", or "Critical")
    • statusToString(Status s): מחזירה את הסטטוס כמחרוזת ("Pending", "InProgress", or "Completed")
  • Task.h: הגדירו מחלקת Task שמשתמשת במחלקות ה-enum שלכם.

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

    ממשו את המתודות הבאות:

    • setStatus(Status s): מעדכנת את הסטטוס של המשימה
    • getPriorityValue(): מחזירה את הערך השלם הבסיסי של העדיפות באמצעות static_cast
    • display(): מדפיסה את המשימה בתבנית: [name] - Priority: [priority] (Value: [value]) - Status: [status]
  • main.cpp: קראו שלושה קלטים:
    1. שם המשימה (מחרוזת)
    2. רמת העדיפות כמספר שלם (1=Low, 2=Medium, 3=High, 4=Critical)
    3. הסטטוס כמספר שלם (0=Pending, 1=InProgress, 2=Completed)

    צרו Task עם השם והעדיפות הנתונים (המירו את המספר השלם לערך המתאים של ה-enum Priority באמצעות static_cast). לאחר מכן הגדירו את הסטטוס שלה על סמך הקלט השלישי. לבסוף, קראו ל-display() כדי להציג את פרטי המשימה.

לדוגמה, עם הקלטים Fix bug, 3 ו-1:

Fix bug - Priority: High (Value: 3) - Status: InProgress

עם הקלטים Write docs, 1 ו-2:

Write docs - Priority: Low (Value: 1) - Status: Completed

עם הקלטים Deploy app, 4 ו-0:

Deploy app - Priority: Critical (Value: 4) - Status: Pending

שימו לב כיצד מחלקות ה-enum שומרות על ערכי העדיפות והסטטוס נפרדים לחלוטין. אי אפשר להשוות בטעות בין Priority ל-Status או להקצות אחד לשני. השימוש המפורש ב-static_cast, שנדרש להמרה בין מספרים שלמים לערכי enum, מבהיר את כוונת הקוד ומונע באגים חמקמקים.

נסו בעצמכם

#include <iostream>
#include <string>
#include "Task.h"

using namespace std;

int main() {
    // קרא את הקלטים
    string taskName;
    int priorityInt;
    int statusInt;
    
    getline(cin, taskName);
    cin >> priorityInt;
    cin >> statusInt;
    
    // TODO: צור Task עם השם והעדיפות שניתנו
    // השתמש ב-static_cast כדי להמיר את priorityInt לערך enum מסוג Priority
    
    // TODO: הגדר את מצב המשימה על סמך statusInt
    // השתמש ב-static_cast כדי להמיר את statusInt לערך enum מסוג Status
    
    // TODO: קרא ל-display() כדי להציג את פרטי המשימה
    
    return 0;
}
quiz iconבחנו את עצמכם

השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.

כל השיעורים ביחידה תכנות מונחה עצמים

תרגלו בעצמכם: קומפיילר C++ אונליין