top of page

C++ Dilinde Enum ve Enum Class

  • Writer: Yusuf Hançar
    Yusuf Hançar
  • May 23, 2023
  • 4 min read

Bu yazımızda yazılım dillerinde yer alan enumeration yani bilindik kısa adıyla enum kavramını ele alacağız. Tabi detaylar daha çok C ve C++ dillerindeki kullanım senaryoları ve gelişim süreçleri değerlendirilmektedir.

Enum kod içerisinde kullanılan sabitlerin tanımlanmasını ve bununla beraber kodun okunurluğunu artırmayı amaçlayan yapısal elemanlar olarak tanımlanabilmektedir. Yani bu sabitlere isim vererek ya da etiket vererek ilişkilendirilmesini sağlamaktadır. Default olarak ilk sabite programcı tarafından atama yapılmaz ise sıfır değeri ile başlar ve artarak diğer sabitler değer alır. Bu temel bilgilendirmenin yanı sıra bilinmesi gereken önemli noktalardan biri olan dönüşüm senaryoları, atama durumları değerlendirilecektir.

Enum temel olarak ele alındıktan sonra eksiklikleri ve yeterli olmadığı noktalarda dile modern c++(11) ile eklenen enum class değerlendirmesi yapılacaktır.

İlk olarak C dilinde enum türü underline type olarak değerlendirilmektedir. int türü ile aynı size değerindedir.

enum Fruits{ Orange, Apple, Banana };
*****************************
AÇIKLAMA: 
*****************************

C++ programlama dilinde kullanılması tavsiye edilmemektedir. Nedeni temelde c++11 ile eklenen enum class denebilir. Detaylandıracak olursak eğer ;

  1. Primitive türlerden(temel veri türleri) enum türlerine ve farklı enum türleri arasında otomatik dönüşüm yokken enum türden primitive türlere dönüşüm vardır.

  2. Enum türünün underline type karşılığı derleyiciye bağlı olduğundan enum türlerinin forward declaration'ı yapılamaz.

NOT : Forward declaration; sınıf veya nesne hakkında bilgi vermeden önce kullanılan bir deyimdir ve genellikle bir header dosyasında yer alır. Sınıflar birbirine referans veriyorsa ve bu nedenle karşılıklı olarak birbirlerini içeren header dosyalarına ihtiyaç duyuluyorsa, forward declaration kullanılarak bu döngüsel bağımlılıkların çözülmesi sağlanabilir. Örneğin, sınıfların veya işlevlerin isimleri forward declaration ile bildirilebilir ve sonra daha sonra tam bir tanım veya implementasyon yapılabilir. Sadece bir işlevin veya sınıfın prototipine ihtiyaç duyulduğu durumlarda, tam bir tanımın veya implementasyonun yapılmasına gerek olmadan forward declaration kullanılabilir. Bu, derleyicinin gereksiz kod oluşturmasını engeller ve derleme süresini ve bellek kullanımını azaltabilir.


  • Şimdi örneklerle enum ve enum class pekiştirmesi yapalım...

enum Fruits{ Orange, Apple, Banana };

int main()
{
    Fruits frt = Orange;
    int val = 2;

    frt = val; 
    val = frt;   
    
    return 0; 
}
*****************************
AÇIKLAMA: frt = val; ataması syntax error ancak diğer atama geçerlidir (implicit type conversion vardır.(otomatik tür dönüşümü vardır)) 
Yukarıdaki ilk madde için değerlendirilebilir.
*****************************
enum Fruits;

class SmartCode {
    Fruits frt;
    int val;
};

int main()
{
    return 0;
}
*****************************
AÇIKLAMA: bu durumda derleyici SmartCode sınıfı türünden nesneler için ne kadarlık alan ayıracağını zor anlaşılır.
enum türünün underline türü ne ise ona göre değişecektir. (int, double ne ise ona göre gibi...)
Ayrıca ilgili enum türünün .h dosyasını eklemek zorunda kalırdık.
*****************************
#include "smart.h"
#include "code.h"

enum Smart { Cpp, Java, Rust };
enum Code { C, Go, Cpp };
*****************************
AÇIKLAMA: 
/> Derlediğimizde syntax error olur. 
/> Nedeni scope kurallarıdır aynı scope içinde aynı isim birden fazla varlığa verilemez.
/> Cpp isimleri burada çakışmaktadır.
*****************************
#include "smart.h"
#include "code.h"

enum Smart { SmartCpp, Java, Rust };
enum Code { C, Go, Cpp };
*****************************
AÇIKLAMA: bu şekilde isim çakışması önlenebilir.
*****************************
#include "smart.h"
#include "code.h"

class SmartCode {
public :
    enum Smart { SmartCpp, Java, Rust };
};

enum Code { C, Go, Cpp };
*****************************
AÇIKLAMA: bu şekilde isim çakışması önlenebilir.
*****************************
#include "smart.h"
#include "code.h"

namespace smartspace
{
    enum Smart { SmartCpp, Java, Rust };
}

enum Code { C, Go, Cpp };
*****************************
AÇIKLAMA: bu şekilde isim çakışması önlenebilir.
*****************************

  • Modern C++ ile eklenen enum class sayesinde tüm bu çözüm yollarına gerek kalmadan daha okunabilir ve performanslı kod yazılabilmektedir.

enum SmartCode : int { SmartCpp, Java, Rust };
enum SmartCode : unsigned char { C, Go, Cpp };
*****************************
AÇIKLAMA: Öncelikle c++11 ile özel bir tam sayı türü yazabilme kabiliyeti eklenmiştir.
*****************************
enum SmartCode : int;

class Myclass {
public :
    SmartCode frt;
    int val;
};
*****************************
AÇIKLAMA: geçerlidir.
*****************************

  • enum class bir type olarak değerlendirilmemektedir. Default olarak integer türü almaktadır. Bu eklenti ile yukarıda bahsedilen forward declaration sorunu çözülmüştür. Diğer türlere de otomatik tür dönüşümü engellenmiştir.

enum Fruits{ Orange, Apple, Banana };

int main()
{
    Fruits frt = Orange;            // syntax error enum scope'u değişti.
    Fruits frt = Fruits::Orange;    // legal.
    White;                          // error 
    int val = frt;                  // syntax error eski c++ da geçerliydi.
    int mx = static_cast<int>(frt); // geçerlidir.
}
*****************************
AÇIKLAMA: cast edilerek dönüşüm geçerli olduğunu göstermek için eklenmiştir.
*****************************
enum class SmartCode : int { Cpp, Java, Rust };
enum class SmartCode : unsigned char { C, Go, Cpp };
*****************************
AÇIKLAMA: İsim çakışması da engellenmiştir.
*****************************

NOT : Çıkış akımına vermek sentaks hatasıdır ve çözüm olarak bir pointer dizisi kullanılabilmektedir.


enum class SmartCode : int { Cpp, Java, Rust };
enum class SmartCode : unsigned char { C, Go, Cpp };
  
int main () 
{ 
    const char* const eptr[] = { "Cpp", "Java" };

    eptr[SmartCode::Cpp]                     // syntax error
    eptr[static_cast<int>(SmartCode::Cpp)]   // legal
}
*****************************
AÇIKLAMA: int türüne otomatik dönüşüm yoktur ve dezavantajlarından biridir.
*****************************
enum SmartCode { Cpp, Java, Rust };

int main ()
{
    SmartCode sc = Cpp;

    ++sc;         
}
*****************************
AÇIKLAMA: hem enum hem de enum class kullanımında syntax error.
Hem eski(outdated) hem de modern c++ da enum türleri ++ operatorunun operandı olamaz.
*****************************
#include <iostream>

using namespace std;

enum class SmartCode { Java, Cpp, Rust, C };

SmartCode operator++(SmartCode& lang) 
{
    return lang = static_cast<SmartCode>(static_cast<int>(lang) + 1);
}

int main()
{
    SmartCode lang = SmartCode::Java;

    cout << "first lang: " << static_cast<int>(lang) << endl;

    ++lang;

    cout << "next language: " << static_cast<int>(lang) << endl;

    return 0;
}
*****************************
AÇIKLAMA: operator overloading ile ++ işlemi legal hale getirildi.
*****************************
enum SmartCode { Java, Cpp, Rust, C };

int main()
{
    SmartCode sc = 1;
}
*****************************
AÇIKLAMA: syntax error
*****************************
#include <iostream>

using namespace std;

enum class Languages{ Java, Cpp, Rust, C };

int main() 
{
    Languages lng = Languages::Java;

    auto show_languages = [](Languages lng) 
    {
        switch(day) 
        {
            case Languages::Java :
            {
                cout << "Java" << endl;
                break;
            }
            case Languages::Cpp :
            {
                cout << "Cpp" << endl;
                break;
            }  
            case Languages::Rust : 
            {
                cout << "Rust" << endl;
                break;
            }   
            case Languages::C :
            {
                cout << "C" << endl;
                break;
            }
        }
    };

    show_languages(lng);

    return 0;
}

ree

 
 
 

Recent Posts

See All
C++ Dilinde [[nodiscard]] attribute

C++’ta [[attribute]] (öznitelik) mekanizması, kod hakkında ek bilgi sağlayarak derleyicinin uyarılar vermesine, belirli optimizasyonlar...

 
 
 
C++ Dilinde constinit

C++20'de tanıtılan önemli bir özellik `constinit`'dir; bu özellik, statik depolama süresine sahip değişkenlerin derleme zamanında...

 
 
 

Comments


bottom of page