typeid
operator
Запрашивает информацию о типе.
Используется там, где dynamic type polymorphic object должен быть известен, а также для статической идентификации типа.
Содержание |
Синтаксис
typeid (
тип
)
|
(1) | ||||||||
typeid (
выражение
)
|
(2) | ||||||||
Выражение typeid является lvalue-выражением , которое ссылается на объект с статической продолжительностью хранения , имеющий const-квалифицированную версию полиморфного типа std::type_info или некоторого типа, производного от него.
Если определение стандартной библиотеки для std::type_info не видимо при использовании typeid , программа является некорректной.
Объяснение
Если type или тип expression является классом или ссылкой на класс, то этот класс не может быть неполным типом .
- Если expression является lvalue (until C++11) glvalue (since C++11) выражением, которое идентифицирует объект полиморфного типа (то есть класса, который объявляет или наследует как минимум одну виртуальную функцию ), то выражение typeid вычисляет выражение и затем ссылается на объект std::type_info , который представляет динамический тип выражения.
-
- Если expression является выражением разыменования и его операнд вычисляется в нулевое значение указателя , выбрасывается исключение типа, соответствующего обработчикам типа std::bad_typeid [1] .
- В противном случае typeid не вычисляет выражение , и объект std::type_info , который он идентифицирует, представляет статический тип выражения. Преобразования lvalue-to-rvalue, array-to-pointer или function-to-pointer не выполняются.
|
(since C++17) |
Если type или тип expression является cv-квалифицированным, результат typeid ссылается на объект std::type_info представляющий тип без cv-квалификаторов (то есть, typeid ( const T ) == typeid ( T ) ).
Если typeid используется для объекта в процессе конструирования или разрушения (в деструкторе или конструкторе, включая список инициализации конструктора или инициализаторы членов по умолчанию ), то объект std::type_info , на который ссылается этот typeid , представляет класс, который конструируется или разрушается, даже если это не самый производный класс.
- ↑ В других контекстах вычисление такого выражения приводит к неопределённому поведению.
Примечания
При применении к выражению полиморфного типа, вычисление выражения typeid может требовать дополнительных затрат времени выполнения (поиск в виртуальной таблице), в противном случае выражение typeid разрешается во время компиляции.
Не определено, вызывается ли деструктор для объекта, на который ссылается typeid в конце выполнения программы.
Нет гарантии, что один и тот же объект
std::type_info
будет использоваться всеми вычислениями выражения typeid для одного типа, хотя они будут сравниваться как равные.
std::type_info::hash_code
этих объектов
type_info
будет идентичным, как и их
std::type_index
.
const std::type_info& ti1 = typeid(A); const std::type_info& ti2 = typeid(A); assert(&ti1 == &ti2); // не гарантируется assert(ti1 == ti2); // гарантируется assert(ti1.hash_code() == ti2.hash_code()); // гарантируется assert(std::type_index(ti1) == std::type_index(ti2)); // гарантируется
Ключевые слова
Пример
Пример, показывающий вывод с использованием одной из реализаций, где type_info::name возвращает полные имена типов; отфильтруйте через c++filt -t при использовании gcc или аналогичного.
#include <iostream> #include <string> #include <typeinfo> struct Base {}; // non-polymorphic struct Derived : Base {}; struct Base2 { virtual void foo() {} }; // polymorphic struct Derived2 : Base2 {}; int main() { int myint = 50; std::string mystr = "string"; double *mydoubleptr = nullptr; std::cout << "myint has type: " << typeid(myint).name() << '\n' << "mystr has type: " << typeid(mystr).name() << '\n' << "mydoubleptr has type: " << typeid(mydoubleptr).name() << '\n'; // std::cout << myint is a glvalue expression of polymorphic type; it is evaluated const std::type_info& r1 = typeid(std::cout << myint); // side-effect: prints 50 std::cout << '\n' << "std::cout<<myint has type : " << r1.name() << '\n'; // std::printf() is not a glvalue expression of polymorphic type; NOT evaluated const std::type_info& r2 = typeid(std::printf("%d\n", myint)); std::cout << "printf(\"%d\\n\",myint) has type : " << r2.name() << '\n'; // Non-polymorphic lvalue is a static type Derived d1; Base& b1 = d1; std::cout << "reference to non-polymorphic base: " << typeid(b1).name() << '\n'; Derived2 d2; Base2& b2 = d2; std::cout << "reference to polymorphic base: " << typeid(b2).name() << '\n'; try { // dereferencing a null pointer: okay for a non-polymorphic expression std::cout << "mydoubleptr points to " << typeid(*mydoubleptr).name() << '\n'; // dereferencing a null pointer: not okay for a polymorphic lvalue Derived2* bad_ptr = nullptr; std::cout << "bad_ptr points to... "; std::cout << typeid(*bad_ptr).name() << '\n'; { catch (const std::bad_typeid& e) { std::cout << " caught " << e.what() << '\n'; { {
Возможный вывод:
======== output from Clang ========
myint has type: i
mystr has type: NSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE
mydoubleptr has type: Pd
50
std::cout<<myint has type : NSt3__113basic_ostreamIcNS_11char_traitsIcEEEE
printf("%d\n",myint) has type : i
reference to non-polymorphic base: 4Base
reference to polymorphic base: 8Derived2
mydoubleptr points to d
bad_ptr points to... caught std::bad_typeid
======== output from MSVC ========
myint has type: int
mystr has type: class std::basic_string<char,struct std::char_traits<char>,⮠
class std::allocator<char> >
mydoubleptr has type: double * __ptr64
50
std::cout<<myint has type : class std::basic_ostream<char,struct std::char_traits<char> >
printf("%d\n",myint) has type : int
reference to non-polymorphic base: struct Base
reference to polymorphic base: struct Derived2
mydoubleptr points to double
bad_ptr points to... caught Attempted a typeid of nullptr pointer!
Отчёты о дефектах
Следующие отчеты об изменениях в поведении, содержащие описания дефектов, были применены ретроактивно к ранее опубликованным стандартам C++.
| DR | Applied to | Behavior as published | Correct behavior |
|---|---|---|---|
| CWG 492 | C++98 |
когда
typeid
применяется к ссылке на cv-квалифицированный
тип, результат представлял ссылочный тип |
результат представляет
cv-неквалифицированный ссылочный тип |
| CWG 1416 | C++98 |
формулировка относительно квалификации верхнего уровня
cv могла быть неверно истолкована |
улучшена формулировка |
| CWG 1431 | C++98 | typeid мог выбрасывать только std::bad_typeid |
разрешено выбрасывать
сопоставимые производные классы |
| CWG 1954 | C++98 |
было неясно, может ли разыменование нулевого указателя
проверяться в подвыражениях expression |
проверяется только на верхнем уровне |
Смотрите также
|
содержит информацию о типе, класс, возвращаемый оператором typeid
(класс) |