2015-01-22 2 views
1

Я два класса 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 нужен хотя бы один виртуальный метод?

+0

Похоже, что дубликат [Typeid не работает корректно] (http://stackoverflow.com/q/18147864/1708801), в основном, если вы добавляете виртуальные методы, вы получите желаемый результат. –

+1

Если вы пишете компилятор, как бы вы реализовали 'typeid'? Я бы, вероятно, сделал это как скрытый виртуальный метод. Но если класс не имеет виртуальных методов (и, следовательно, нет vtable), это невозможно. Я думаю, что спецификация C++ была написана для этого. –

+0

Вы указали 'ptr' как' Base * '. Что еще вы ожидаете? Это не похоже на Java, у которого есть проверка типа времени выполнения. C++ полностью статичен. – texasbruce

ответ

4

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

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

0

Too long for a comment.

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

2) Рассматривает выражение экспрессии

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

б) Если выражение не является выражение полиморфного типа glvalue , TypeId не оценивает выражение и станд :: type_info объекта идентифицирует представляет статического типа выражения. Lvalue-to-rvalue, array-to-pointer или преобразования функции-к-указателю не выполняются.

Таким образом, поведение ожидается, поскольку в одном случае класс является полиморфным, а в другом - нет.

Смежные вопросы