Çalışma zamanı türü bilgileri - Run-time type information

Bilgisayar programlamada, çalışma zamanı türü bilgisi veya çalışma zamanı tip tanımlama (RTTI)[1] bir özelliğidir C ++ bir nesnenin bilgileri hakkında bilgi veren programlama dili veri tipi -de Çalışma süresi. Çalışma zamanı türü bilgileri, tamsayılar ve karakterler gibi basit veri türleri veya genel türler için geçerli olabilir. Bu, daha genel bir kavramın C ++ uzmanlığıdır. iç gözlem yazın. Benzer mekanizmalar, diğer programlama dillerinde de bilinmektedir. Nesne Pascal (Delphi ).

Orijinal C ++ tasarımında, Bjarne Stroustrup bu mekanizmanın sıklıkla kötüye kullanıldığını düşündüğü için çalışma zamanı türü bilgileri içermiyordu.[2]

Genel Bakış

C ++ 'da, güvenli yapmak için RTTI kullanılabilir tip yayınlar, kullanmak dynamic_cast <> işleci ve çalışma zamanında tür bilgilerini değiştirmek için typeid operatör ve std :: type_info sınıf.

RTTI yalnızca şu sınıflar için mevcuttur: polimorfik yani en az bir sanal yöntem. Uygulamada, bu bir sınırlama değildir çünkü temel sınıfların bir sanal yıkıcı türetilmiş sınıfların nesnelerinin temel işaretçiden silinmeleri durumunda düzgün temizleme gerçekleştirmesine izin vermek için.

RTTI, bazı derleyicilerde isteğe bağlıdır; programcı derleme sırasında işlevselliği dahil edip etmemeyi seçebilir. Bir program onu ​​kullanmasa bile RTTI'yi kullanılabilir hale getirmenin bir kaynak maliyeti olabilir.

typeid

typeid anahtar kelime belirlemek için kullanılır sınıf bir nesne -de Çalışma süresi. Döndürür referans -e std :: type_info programın sonuna kadar var olan nesne.[3] Kullanımı typeid, polimorfik olmayan bir bağlamda, genellikle dynamic_cast <sınıf_türü> sadece sınıf bilgisinin gerekli olduğu durumlarda, çünkü typeid her zaman bir sabit zamanlı prosedür, oysa dynamic_cast çalışma zamanında argümanının sınıf türetme kafesini geçmesi gerekebilir.[kaynak belirtilmeli ] Döndürülen nesnenin bazı yönleri uygulama tanımlıdır, örneğin std :: type_info :: isim ()ve tutarlı olması için derleyiciler arasında güvenilemez.

Sınıfın nesneleri std :: bad_typeid ifadesi ne zaman atılır typeid tekli * operatörünün bir boş işaretçisi. Diğer boş referans argümanları için bir istisna atılıp atılmayacağı uygulamaya bağlıdır. Başka bir deyişle, istisnanın garanti edilebilmesi için ifadenin form alması gerekir. typeid (* p) nerede p boş gösterici ile sonuçlanan herhangi bir ifadedir.

Misal

#Dahil etmek <iostream>#Dahil etmek <typeinfo>sınıf Kişi {halka açık:    gerçek ~Kişi() = varsayılan;};sınıf Çalışan : halka açık Kişi {};int ana() {    Kişi kişi;    Çalışan işçi;    Kişi* ptr = &işçi;    Kişi& ref = işçi;        // typeid :: name tarafından döndürülen dizge uygulama tanımlıdır.    std::cout << typeid(kişi).isim()              << std::son;  // Kişi (derleme sırasında statik olarak bilinir).    std::cout << typeid(işçi).isim()              << std::son;  // Çalışan (derleme zamanında statik olarak bilinir).    std::cout << typeid(ptr).isim()              << std::son;  // Kişi * (derleme sırasında statik olarak bilinir).    std::cout << typeid(*ptr).isim()              << std::son;  // Çalışan (çalışma zamanında dinamik olarak baktı                             // çünkü bu, bir                             // polimorfik bir sınıfa işaretçi).    std::cout << typeid(ref).isim()              << std::son;  // Çalışan (referanslar polimorfik de olabilir)    Kişi* p = nullptr;        Deneyin {        typeid(*p); // Tanımsız davranış; std :: bad_typeid değerini atar.    } tutmak (...) { }    Kişi& p_ref = *p; // Tanımsız davranış: boş referansın kaldırılması    typeid(p_ref);      // std :: bad_typeid atmak için gereksinimleri karşılamıyor                        // çünkü typeid için ifade sonuç değil                        // tekli * operatörünü uygulama.}

Çıktı (kesin çıktı sisteme ve derleyiciye göre değişir):

PersonEmployeePerson * EmployeeEmployee

dynamic_cast ve Java yayını

dynamic_cast operatör C ++ için kullanılır aşağılık daha spesifik bir türe bir başvuru veya işaretçi sınıf hiyerarşisi. Aksine static_cast, hedefi dynamic_cast olmalı Işaretçi veya referans -e sınıf. Aksine static_cast ve C tarzı typecast (derleme sırasında tip kontrolünün yapıldığı), bir tip güvenlik kontrolü yapılır. Çalışma süresi. Türler uyumlu değilse, bir istisna fırlatılacak (ile uğraşırken Referanslar ) veya a boş işaretçisi iade edilecek (ile uğraşırken işaretçiler ).

Bir Java typecast benzer şekilde davranır; dönüştürülen nesne aslında hedef türün bir örneği değilse ve dil tanımlı bir yöntemle birine dönüştürülemiyorsa, java.lang.ClassCastException fırlatılacak.[4]

Misal

Bazılarını varsayalım işlevi alır nesne tip Bir argüman olarak ve iletilen nesne bir örnekse bazı ek işlemler gerçekleştirmek istiyor B, bir alt sınıf nın-nin Bir. Bu, kullanılarak gerçekleştirilebilir dynamic_cast aşağıdaki gibi.

#Dahil etmek <array>#Dahil etmek <iostream>#Dahil etmek <memory>#Dahil etmek <typeinfo>kullanma ad alanı std;sınıf Bir {halka açık:    // RTTI sanal yöntem tablosuna dahil edildiğinden, şurada olmalıdır:    // en az bir sanal işlev.    gerçek ~Bir() = varsayılan;    geçersiz MethodSpecificToA() {        cout << "A için özel yöntem çağrıldı" << son;    }};sınıf B: halka açık Bir {halka açık:    geçersiz MethodSpecificToB() {        cout << "B'ye özel yöntem çağrıldı" << son;    }};geçersiz İşlevim(Bir& my_a) {    Deneyin {        // Cast, yalnızca B tipi nesneler için başarılı olacaktır.        B& benim_b = dynamic_cast<B&>(my_a);        benim_b.MethodSpecificToB();    } tutmak (sabit bad_cast& e) {        Cerrah << "İstisna" << e.ne() << "atıldı." << son;        Cerrah << "Nesne B tipi değil" << son;    }}int ana() {    dizi<unique_ptr<Bir>, 3> array_of_a; // A temel sınıfına işaretçiler dizisi    array_of_a[0] = make_unique<B>();   // İşaretçi B nesnesine.    array_of_a[1] = make_unique<B>();   // İşaretçi B nesnesine.    array_of_a[2] = make_unique<Bir>();   // Bir nesneye işaretçi.    için (int ben = 0; ben < 3; ++ben)        İşlevim(*array_of_a[ben]);}

Konsol çıkışı:

B'ye özel yöntem çağrıldı B'ye özgü yöntem çağrıldı İstisna std :: kötü_yayın atıldı Nesne B türünde değil

Benzer bir versiyonu İşlevim ile yazılabilir işaretçiler onun yerine Referanslar:

geçersiz İşlevim(Bir* my_a) {    B* benim_b = dynamic_cast<B*>(my_a);    Eğer (benim_b != nullptr)        benim_b->methodSpecificToB();    Başka        std::Cerrah << "Nesne B tipi değil" << std::son;}

Ayrıca bakınız

Referanslar

  1. ^ Sun Microsystems (2000). "Çalışma Zamanı Türü Tanımlama". C ++ Programlama Kılavuzu. Oracle. Alındı 16 Nisan 2015.
  2. ^ Bjarne Stroustrup (Mart 1993). "C ++ Tarihi: 1979-1991" (PDF). Bjarne Stroustrup. s. 50. Alındı 2009-05-18.
  3. ^ C ++ standardı (ISO / IEC14882) bölüm 5.2.8 [ifade türü], 18.5.1 [lib.type.info] - http://cs.nyu.edu/courses/fall11/CSCI-GA.2110-003/documents/c++2003std.pdf
  4. ^ http://docs.oracle.com/javase/8/docs/api/java/lang/ClassCastException.html

Dış bağlantılar