Menu
Coddy logo textTech

Enum Sınıfları ve Güçlü Tiplendirme

Coddy'nin C++ Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 80 / 104.

C++11, geleneksel C tarzı enum'ların eksikliklerini gidermek için enum classes (kapsamlı numaralandırmalar olarak da adlandırılır) özelliğini getirdi. Bunlar daha güçlü tür güvenliği sağlar ve numaralandırma değerlerinin yanlışlıkla hatalı kullanımını önler.

Geleneksel enum'ların sorunları vardır: değerleri çevreleyen kapsama sızar ve dolaylı olarak tam sayılara dönüşerek fark edilmesi zor hatalara yol açar:

// Geleneksel enum - sorunlu
enum Color { Red, Green, Blue };
enum TrafficLight { Red, Yellow, Green };  // Hata! Red ve Green zaten tanımlanmış

int x = Red;  // Dolaylı olarak int'e (0) dönüşür
if (Red == 0) { }  // Derlenir - enum ile int karşılaştırılıyor

Enum sınıfları, değerleri kapsam içine alarak ve örtük dönüşümleri engelleyerek bu sorunları çözer:

enum class Color { Red, Green, Blue };
enum class TrafficLight { Red, Yellow, Green };  // Tamam - çakışma yok

Color c = Color::Red;      // Kapsam operatörü kullanılmalıdır
// int x = c;              // Hata! Örtük dönüşüm yok
int x = static_cast<int>(c);  // Açık dönüşüm gereklidir

// if (c == 0) { }         // Hata! int ile karşılaştırılamaz
if (c == Color::Red) { }   // Tamam - aynı türler karşılaştırılıyor

Bellek kontrolü için temel türü de belirtebilirsiniz:

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

Enum sınıfları, OOP tasarımlarıyla iyi entegre olur, kodu daha okunabilir hale getirir ve tür hatalarını çalışma zamanı yerine derleme zamanında yakalar.

challenge icon

Görev

Kolay

Farklı öncelik seviyelerini ve görev durumlarını temsil etmek için enum sınıflarını kullanan bir görev öncelik sistemi oluşturalım. Bu, enum sınıflarının nasıl tip güvenliği sağladığını ve geleneksel enum'larda ortaya çıkan hata türlerini nasıl önlediğini gösterir.

Kodunuzu üç dosya halinde düzenleyeceksiniz:

  • TaskTypes.h: Görev sistemi için enum sınıflarınızı tanımlayın.

    Şu değerlere sahip bir Priority enum sınıfı oluşturun: Low, Medium, High ve Critical. Temel tür olarak int belirtin ve değerleri sırasıyla 1, 2, 3 ve 4 olsun.

    Şu değerlere sahip bir Status enum sınıfı oluşturun: Pending, InProgress ve Completed.

    İki yardımcı fonksiyon sağlayın:

    • priorityToString(Priority p) — önceliği bir dize olarak döndürür ("Low", "Medium", "High" veya "Critical")
    • statusToString(Status s) — durumu bir dize olarak döndürür ("Pending", "InProgress" veya "Completed")
  • Task.h: Enum sınıflarınızı kullanan bir Task sınıfı tanımlayın.

    Task sınıfınız bir isim (string), bir Priority ve bir Status saklamalıdır. Kurucu (constructor) bir isim ve öncelik almalı, durum varsayılan olarak Status::Pending olmalıdır.

    Şu metotları uygulayın:

    • setStatus(Status s) — görevin durumunu günceller
    • getPriorityValue()static_cast kullanarak önceliğin temel tam sayı değerini döndürür
    • display() — görevi şu formatta yazdırır: [name] - Priority: [priority] (Value: [value]) - Status: [status]
  • main.cpp: Üç girdi okuyun:
    1. Görev adı (string)
    2. Tam sayı olarak öncelik seviyesi (1=Low, 2=Medium, 3=High, 4=Critical)
    3. Tam sayı olarak durum (0=Pending, 1=InProgress, 2=Completed)

    Verilen isim ve öncelik ile bir Task oluşturun (tam sayıyı static_cast kullanarak uygun Priority enum değerine dönüştürün). Ardından üçüncü girdiye göre durumunu ayarlayın. Son olarak, görev ayrıntılarını göstermek için display() metodunu çağırın.

Örneğin, Fix bug, 3 ve 1 girdileriyle:

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

Write docs, 1 ve 2 girdileriyle:

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

Deploy app, 4 ve 0 girdileriyle:

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

Enum sınıflarının öncelik ve durum değerlerini nasıl tamamen ayrı tuttuğuna dikkat edin; yanlışlıkla bir Priority değerini bir Status değeriyle karşılaştıramaz veya birini diğerine atayamazsınız. Tam sayılar ve enum değerleri arasında dönüşüm yapmak için gereken açık static_cast kullanımı, kodun amacını netleştirir ve sinsi hataları önler.

Kopya kağıdı

C++11, geleneksel C tarzı enum'lardan daha güçlü tip güvenliği sağlamak için enum sınıflarını (kapsamlı numaralandırmalar - scoped enumerations) tanıttı.

Geleneksel enum'lar, kapsam sızıntısı (scope leakage) ve örtük dönüşümlerle (implicit conversions) ilgili sorunlara sahiptir:

// Geleneksel enum - problemli
enum Color { Red, Green, Blue };
enum TrafficLight { Red, Yellow, Green };  // Hata! Red ve Green zaten tanımlanmış

int x = Red;  // Örtük olarak int'e dönüşür
if (Red == 0) { }  // Derlenir - enum ile int karşılaştırılıyor

Enum sınıfları, kapsam çözünürlüğü (scope resolution) gerektirerek ve örtük dönüşümleri engelleyerek bu sorunları çözer:

enum class Color { Red, Green, Blue };
enum class TrafficLight { Red, Yellow, Green };  // Tamam - çakışma yok

Color c = Color::Red;      // Kapsam operatörü kullanılmalı
// int x = c;              // Hata! Örtük dönüşüm yok
int x = static_cast<int>(c);  // Açık dönüşüm (explicit conversion) gerekli

// if (c == 0) { }         // Hata! int ile karşılaştırılamaz
if (c == Color::Red) { }   // Tamam - aynı tipler karşılaştırılıyor

Bellek kontrolü için temel veri tipini (underlying type) belirtebilirsiniz:

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

Enum sınıfları ve tam sayılar arasında dönüşüm yapmak için açık döküm (explicit casting) kullanın:

// Tam sayıdan enum sınıfına
Priority p = static_cast<Priority>(3);

// Enum sınıfından tam sayıya
int value = static_cast<int>(p);

Kendin dene

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

using namespace std;

int main() {
    // Girdileri oku
    string taskName;
    int priorityInt;
    int statusInt;
    
    getline(cin, taskName);
    cin >> priorityInt;
    cin >> statusInt;
    
    // TODO: Verilen isim ve öncelik ile bir Task oluşturun
    // priorityInt değerini Priority enum türüne dönüştürmek için static_cast kullanın
    
    // TODO: statusInt değerine göre görevin durumunu (status) ayarlayın
    // statusInt değerini Status enum türüne dönüştürmek için static_cast kullanın
    
    // TODO: Görev ayrıntılarını göstermek için display() fonksiyonunu çağırın
    
    return 0;
}
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Nesne Yönelimli Programlama bölümündeki tüm dersler