Share via


Numaralandırmalar [C++]

Numaralandırma, numaralandırıcı olarak bilinen adlandırılmış integral sabitlerinden oluşan kullanıcı tanımlı bir türdür.

Dekont

Bu makale, C++11'de kullanıma sunulan ISO Standart C++ Dil enum türünü ve kapsamlı (veya kesin olarak belirlenmiş) enum class türü kapsar. C++/CLI ve C++/CX içindeki veya türleri hakkında public enum class bilgi için bkzenum class. (C++/CLI ve C++/CX).private enum class

Sözdizimi

enum-name:
identifier

enum-specifier:
enum-head{enumerator-listTercih}
enum-head { enumerator-list , }

enum-head:
enum-keyattribute-specifier-seqoptenum-head-nameopt optenum-base

enum-head-name:
nested-name-specifierTercihidentifier

opaque-enum-declaration:
enum-keyattribute-specifier-seqtercih etenum-head-nameenum-base;

enum-key:
enum
enum class
enum struct

enum-base:
: type-specifier-seq

enumerator-list:
enumerator-definition
enumerator-list , enumerator-definition

enumerator-definition:
enumerator
enumerator = constant-expression

enumerator:
identifierattribute-specifier-seqTercih

Kullanım

// unscoped enum:
// enum [identifier] [: type] {enum-list};

// scoped enum:
// enum [class|struct] [identifier] [: type] {enum-list};

// Forward declaration of enumerations  (C++11):
enum A : int;          // non-scoped enum must have type specified
enum class B;          // scoped enum defaults to int but ...
enum class C : short;  // ... may have any integral underlying type

Parametreler

identifier
Sabit listesi için verilen tür adı.

type
Numaralandırıcıların temel türü; tüm numaralandırıcılar aynı temel türe sahiptir. Herhangi bir tam sayı türünde olabilir.

enum-list
Numaralandırmadaki numaralandırıcıların virgülle ayrılmış listesi. Kapsamdaki her numaralandırıcı veya değişken adı benzersiz olmalıdır. Ancak, değerler yinelenebilir. Kapsamsız bir numaralandırmada kapsam, çevresindeki kapsamdır; kapsamı belirlenmiş bir numaralandırmada kapsam kendisidir enum-list . Kapsamlı bir sabit listesinde liste boş olabilir ve bu da yeni bir tam sayı türünü tanımlar.

class
Bildirimde bu anahtar sözcüğü kullanarak numaralandırmanın kapsamlı olduğunu ve sağlanması identifier gerektiğini belirtirsiniz. Anahtar sözcüğünü struct , bu bağlamdaki diğer eşdeğerleri olduğu için yerine classde kullanabilirsiniz.

Numaralandırıcı kapsamı

Numaralandırma, adlandırılmış sabitler olarak temsil edilen bir değer aralığını tanımlamak için bağlam sağlar. Bu adlandırılmış sabitler numaralandırıcı olarak da adlandırılır. Özgün C ve C++ enum türlerinde, nitelenmemiş numaralandırıcılar bildirildiği enum kapsam boyunca görünür. Kapsamlı sabit listelerinde, numaralandırıcı adı tür adına göre nitelenmelidir enum . Aşağıdaki örnekte, iki sabit listesi türü arasındaki bu temel fark gösterilmektedir:

namespace CardGame_Scoped
{
    enum class Suit { Diamonds, Hearts, Clubs, Spades };

    void PlayCard(Suit suit)
    {
        if (suit == Suit::Clubs) // Enumerator must be qualified by enum type
        { /*...*/}
    }
}

namespace CardGame_NonScoped
{
    enum Suit { Diamonds, Hearts, Clubs, Spades };

    void PlayCard(Suit suit)
    {
        if (suit == Clubs) // Enumerator is visible without qualification
        { /*...*/
        }
    }
}

Numaralandırmadaki her ada, sabit listesi içindeki değerlerin sırasına karşılık gelen bir tamsayı değeri atanır. Varsayılan olarak, ilk değere 0 atanır, bir sonrakine 1 atanır ve bu şekilde devam edilir, ancak burada gösterildiği gibi bir numaralandırıcının değerini açıkça ayarlayabilirsiniz:

enum Suit { Diamonds = 1, Hearts, Clubs, Spades };

Numaralandırıcıya Diamonds değeri 1atanır. Sonraki numaralandırıcılar, açık bir değer verilmediyse, önceki numaralandırıcının değerini ve bir değerini alır. Önceki örnekte Hearts 2 Clubs değeri, 3 gibi bir değere sahip olacaktır.

Her numaralandırıcı bir sabit olarak ele alınır ve tanımlandığı enum kapsamda (kapsamsız sabit listeleri için) veya kendi içinde enum (kapsamlı sabit listeleri için) benzersiz bir ada sahip olmalıdır. Adlara verilen değerlerin benzersiz olması gerekmez. Örneğin, kapsamsız bir sabit listesi Suitbildirimini göz önünde bulundurun:

enum Suit { Diamonds = 5, Hearts, Clubs = 4, Spades };

, Hearts, Clubsve Spades değerleri Diamondssırasıyla 5, 6, 4 ve 5'tir. 5'in birden çok kez kullanıldığına dikkat edin; hedeflenmese bile izin verilir. Bu kurallar kapsamlı sabit listeleri için aynıdır.

Atama kuralları

Kapsamsız sabit sabitleri örtük olarak dönüştürülebilir int, ancak hiçbir int zaman örtük olarak sabit listesi değerine dönüştürülemez. Aşağıdaki örnekte, olmayan Suitbir değer atamaya hand çalıştığınızda ne olacağı gösterilmektedir:

int account_num = 135692;
Suit hand;
hand = account_num; // error C2440: '=' : cannot convert from 'int' to 'Suit'

Bir öğesini kapsamlı veya kapsamsız bir numaralandırıcıya dönüştürmek int için bir atama gereklidir. Ancak, kapsamsız bir numaralandırıcıyı, atama olmadan bir tamsayı değerine yükseltebilirsiniz.

int account_num = Hearts; //OK if Hearts is in an unscoped enum

Örtük dönüştürmeleri bu şekilde kullanmak istenmeyen yan etkilere yol açabilir. Kapsamsız sabit listeleriyle ilişkili programlama hatalarını ortadan kaldırmaya yardımcı olmak için kapsamlı sabit listesi değerleri kesin olarak yazılır. Kapsamlandırılmış numaralandırıcıların numaralandırma türü adı (tanımlayıcı) tarafından nitelenmiş olması gerekir ve aşağıdaki örnekte gösterildiği gibi örtük olarak dönüştürülemez:

namespace ScopedEnumConversions
{
    enum class Suit { Diamonds, Hearts, Clubs, Spades };

    void AttemptConversions()
    {
        Suit hand;
        hand = Clubs; // error C2065: 'Clubs' : undeclared identifier
        hand = Suit::Clubs; //Correct.
        int account_num = 135692;
        hand = account_num; // error C2440: '=' : cannot convert from 'int' to 'Suit'
        hand = static_cast<Suit>(account_num); // OK, but probably a bug!!!

        account_num = Suit::Hearts; // error C2440: '=' : cannot convert from 'Suit' to 'int'
        account_num = static_cast<int>(Suit::Hearts); // OK
    }
}

Satırın hand = account_num; daha önce gösterildiği gibi kapsamsız sabit listeleriyle oluşan hataya neden olduğuna dikkat edin. Açık bir atama ile buna izin verilir. Ancak, kapsamı belirlenmiş sabit listeleri ile, bir sonraki deyiminde account_num = Suit::Hearts;dönüştürme girişimine, artık açık bir atama olmadan izin verilmez.

Numaralandırıcısı olmayan sabit listeleri

Visual Studio 2017 sürüm 15.3 ve üzeri (ve üzeri ile /std:c++17 kullanılabilir): Açık bir temel türü olan ve numaralandırıcı içermeyen bir sabit listesi (normal veya kapsamlı) tanımlayarak, başka bir türe örtük dönüştürmesi olmayan yeni bir tamsayı türü sunabilirsiniz. Yerleşik temel türü yerine bu türü kullanarak, yanlışlıkla örtük dönüştürmelerin neden olduğu küçük hatalar olasılığını ortadan kaldırabilirsiniz.

enum class byte : unsigned char { };

Yeni tür, temel alınan türün tam bir kopyasıdır ve bu nedenle aynı çağrı kuralına sahiptir; bu da herhangi bir performans cezası olmadan ABI'ler arasında kullanılabildiği anlamına gelir. Türün değişkenleri doğrudan liste başlatma kullanılarak başlatıldığında atama gerekmez. Aşağıdaki örnekte, çeşitli bağlamlarda numaralandırıcı olmadan numaralandırmaları başlatma gösterilmektedir:

enum class byte : unsigned char { };

enum class E : int { };
E e1{ 0 };
E e2 = E{ 0 };

struct X
{
    E e{ 0 };
    X() : e{ 0 } { }
};

E* p = new E{ 0 };

void f(E e) {};

int main()
{
    f(E{ 0 });
    byte i{ 42 };
    byte j = byte{ 42 };

    // unsigned char c = j; // C2440: 'initializing': cannot convert from 'byte' to 'unsigned char'
    return 0;
}

Ayrıca bkz.

C Numaralandırma bildirimleri
Anahtar Sözcükler