Странное поведение информации о типах во время выполнения

У меня есть два класса Base и Derived следующим образом:

class Base
{
public:
};

class Derived : public Base
{
public:
};

и основная функция:

int main()
{
    Base* ptr = new Derived;

    std::cout << typeid(*ptr).name() << endl;

    delete ptr;

    system("pause");
}

Выходные данные программы показывают class Base там, где я ожидал увидеть class Derived. Но когда я добавил виртуальный метод в класс Base, теперь на выходе отображается class Derived!

Зачем RTTI хотя бы один виртуальный метод?


person Farhad Reza    schedule 22.01.2015    source источник
comment
Похоже, что дубликат Typeid работает неправильно, в основном, если вы добавите виртуальные методы, вы получите желаемый результат.   -  person Shafik Yaghmour    schedule 22.01.2015
comment
Если бы вы писали компилятор, как бы вы реализовали typeid? Я бы, наверное, сделал это как скрытый виртуальный метод. Но если в классе нет виртуальных методов (и, следовательно, vtable), это невозможно. Я думаю, что спецификация C++ была написана для этого.   -  person Mark Ransom    schedule 22.01.2015
comment
Вы объявили ptr как Base*. Что еще вы ожидаете? Это не похоже на Java, у которой есть проверка типов во время выполнения. C++ полностью статичен.   -  person texasbruce    schedule 22.01.2015
comment
@texasbruce: Конечно, но программа дает ожидаемый результат, когда класс Base имеет хотя бы один виртуальный метод, и это было моей точкой зрения.   -  person Farhad Reza    schedule 22.01.2015


Ответы (2)


Потому что так написано в спецификации языка. RTTI работает только с полиморфными типами; то есть типы с виртуальными функциями. Для других типов typeid возвращает информацию о типе для статического типа своего аргумента.

Если вы спрашиваете об обосновании этого: у него есть затраты времени выполнения (как правило, указатель в каждом объекте на метаданные для каждого класса, который поддерживает как виртуальную диспетчеризацию, так и RTTI), и было бы позором, если бы вы приходилось платить эту цену за все типы, независимо от того, хотите ли вы использовать на них RTTI.

person Mike Seymour    schedule 22.01.2015

Слишком длинный комментарий.

1) Относится к объекту std::type_info, представляющему тип типа. Если type является ссылочным типом, результат ссылается на ссылочный тип.

2) Проверяет выражение expression

a) Если выражение является выражением glvalue, которое идентифицирует объект полиморфного типа (т. е. класс, который объявляет или наследует хотя бы одну виртуальную функцию), выражение typeid оценивает выражение, а затем ссылается на объект std::type_info, представляющий динамический тип выражения. Если результатом оцениваемого выражения является нулевой указатель, создается исключение типа std::bad_typeid или типа, производного от std::bad_typeid.

b) Если выражение не является выражением glvalue полиморфного типа, typeid не оценивает выражение, а идентифицируемый им объект std::type_info представляет статический тип выражения. Преобразования Lvalue-to-Rvalue, массива в указатель или функции в указатель не выполняются.

Такое поведение ожидаемо, так как в одном случае класс полиморфен, а в другом нет.

person Luchian Grigore    schedule 22.01.2015