Informace o typu běhu - Run-time type information
tento článek vyžaduje pozornost odborníka na výpočetní techniku.Říjen 2019) ( |
V počítačovém programování informace o typu běhu nebo identifikace typu za běhu (RTTI)[1] je funkce C ++ programovací jazyk, který odhaluje informace o objektu datový typ na runtime. Informace o typu běhu lze použít na jednoduché datové typy, jako jsou celá čísla a znaky, nebo na obecné typy. Toto je C ++ specializace obecnějšího konceptu s názvem introspekce typu. Podobné mechanismy jsou známé i v jiných programovacích jazycích, například Objekt Pascal (Delphi ).
V původním designu C ++ Bjarne Stroustrup nezahrnul informace o typu běhu, protože si myslel, že tento mechanismus byl často zneužíván.[2]
Přehled
V C ++ lze k zajištění bezpečnosti použít RTTI obsadit, za použití dynamic_cast <>
operátor a manipulovat s typovými informacemi za běhu pomocí psí typ
provozovatel a std :: type_info
třída.
RTTI je k dispozici pouze pro třídy, které jsou polymorfní, což znamená, že mají alespoň jeden virtuální metoda. V praxi to není omezení, protože základní třídy musí mít a virtuální destruktor umožnit objektům odvozených tříd provést správné vyčištění, pokud jsou odstraněny ze základního ukazatele.
RTTI je u některých překladačů volitelné; programátor si může v době kompilace zvolit, zda má tuto funkci zahrnout. Zpřístupnění RTTI může být nákladné, i když jej program nepoužívá.
psí typ
The psí typ
klíčové slovo se používá k určení třída z objekt na doba běhu. Vrací a odkaz na std :: type_info
objekt, který existuje až do konce programu.[3] Použití psí typ
, v nepolymorfním kontextu, je často upřednostňován před dynamic_cast <typ_typu>
v situacích, kdy jsou potřeba pouze informace o třídě, protože psí typ
je vždy konstantní čas postup, zatímco dynamic_cast
možná bude potřeba za běhu projít mřížkou odvození třídy svého argumentu.[Citace je zapotřebí ] Některé aspekty vráceného objektu jsou definovány implementací, například std :: type_info :: name ()
, a nelze na něj spoléhat, aby byl konzistentní.
Předměty třídy std :: bad_typeid
jsou vyvolány, když výraz pro psí typ
je výsledkem použití unárního * operátoru na a nulový ukazatel. Zda je vyvolána výjimka pro další argumenty nulového odkazu, závisí na implementaci. Jinými slovy, aby byla zaručena výjimka, musí mít výraz formu psací stroj (* p)
kde str
je libovolný výraz, jehož výsledkem je nulový ukazatel.
Příklad
#zahrnout <iostream>#zahrnout <typeinfo>třída Osoba {veřejnost: virtuální ~Osoba() = výchozí;};třída Zaměstnanec : veřejnost Osoba {};int hlavní() { Osoba osoba; Zaměstnanec zaměstnanec; Osoba* ptr = &zaměstnanec; Osoba& ref = zaměstnanec; // Řetězec vrácený typem :: název je definován implementací. std::cout << psí typ(osoba).název() << std::konec; // Osoba (staticky známá v době kompilace). std::cout << psí typ(zaměstnanec).název() << std::konec; // Zaměstnanec (staticky známý v době kompilace). std::cout << psí typ(ptr).název() << std::konec; // Osoba * (staticky známá v době kompilace). std::cout << psí typ(*ptr).název() << std::konec; // Zaměstnanec (dynamicky vyhledával za běhu // protože je to dereference a // ukazatel na polymorfní třídu). std::cout << psí typ(ref).název() << std::konec; // Zaměstnanec (reference mohou být také polymorfní) Osoba* str = nullptr; Snaž se { psí typ(*str); // Nedefinované chování; hodí std :: bad_typeid. } chytit (...) { } Osoba& p_ref = *str; // Nedefinované chování: dereferencování null psí typ(p_ref); // nesplňuje požadavky na házení std :: bad_typeid // protože výraz pro typeid není výsledkem // použití unárního * operátoru.}
Výstup (přesný výstup se liší podle systému a kompilátoru):
PersonEmployeePerson * EmployeeEmployee
dynamic_cast a Java cast
The dynamic_cast
operátor v C ++ se používá pro vylidňování odkaz nebo ukazatel na konkrétnější typ v hierarchie tříd. Na rozdíl od static_cast
, cíl dynamic_cast
musí být ukazatel nebo odkaz na třída. Na rozdíl od static_cast
a C-styl typecast (kde se kontrola typu provádí během kompilace), kontrola typu se provádí na runtime. Pokud typy nejsou kompatibilní, zobrazí se výjimka bude hozen (při jednání s Reference ) nebo a nulový ukazatel bude vrácen (při jednání s ukazatele ).
A Jáva Typecast se chová podobně; pokud přenášený objekt není ve skutečnosti instancí cílového typu a nelze jej převést na jeden metodou definovanou jazykem, instance java.lang.ClassCastException
bude hozen.[4]
Příklad
Předpokládejme nějaké funkce bere objekt typu A
jako svůj argument a přeje si provést nějakou další operaci, pokud je předaný objekt instancí B
, a podtřída z A
. Toho lze dosáhnout pomocí dynamic_cast
jak následuje.
#zahrnout <array>#zahrnout <iostream>#zahrnout <memory>#zahrnout <typeinfo>použitím jmenný prostor std;třída A {veřejnost: // Protože RTTI je zahrnuto v tabulce virtuálních metod, mělo by být na // alespoň jedna virtuální funkce. virtuální ~A() = výchozí; prázdnota MethodSpecificToA() { cout << „Byla vyvolána metoda specifická pro A“ << konec; }};třída B: veřejnost A {veřejnost: prázdnota MethodSpecificToB() { cout << "Byla vyvolána metoda specifická pro B" << konec; }};prázdnota MyFunction(A& my_a) { Snaž se { // Cast bude úspěšný pouze u objektů typu B. B& my_b = dynamic_cast<B&>(my_a); my_b.MethodSpecificToB(); } chytit (konst bad_cast& E) { cerr << „Výjimka“ << E.co() << „hozen.“ << konec; cerr << "Objekt není typu B" << konec; }}int hlavní() { pole<unique_ptr<A>, 3> pole_a_a; // Pole ukazatelů na základní třídu A. pole_a_a[0] = make_unique<B>(); // Ukazatel na objekt B. pole_a_a[1] = make_unique<B>(); // Ukazatel na objekt B. pole_a_a[2] = make_unique<A>(); // Ukazatel na objekt A. pro (int i = 0; i < 3; ++i) MyFunction(*pole_a_a[i]);}
Výstup konzoly:
Byla vyvolána metoda specifická pro B Metoda specifická pro B byla vyvolána Výjimka std :: bad_cast vyvolána. Objekt není typu B
Podobná verze MyFunction
lze psát s ukazatele namísto Reference:
prázdnota MyFunction(A* my_a) { B* my_b = dynamic_cast<B*>(my_a); -li (my_b != nullptr) my_b->methodSpecificToB(); jiný std::cerr << "Objekt není typu B" << std::konec;}
Viz také
Reference
- ^ Sun Microsystems (2000). „Runtime Type Identification“. Průvodce programováním v C ++. Věštec. Citováno 16. dubna 2015.
- ^ Bjarne Stroustrup (Březen 1993). „A History of C ++: 1979—1991“ (PDF). Bjarne Stroustrup. str. 50. Citováno 2009-05-18.
- ^ C ++ standard (ISO / IEC14882) oddíl 5.2.8 [expr.typeid], 18.5.1 [lib.type.info] - http://cs.nyu.edu/courses/fall11/CSCI-GA.2110-003/documents/c++2003std.pdf
- ^ http://docs.oracle.com/javase/8/docs/api/java/lang/ClassCastException.html