Typeid работает некорректно

Я не могу правильно получить функцию typeid. Я что-то упускаю

Код:

class A
{
     public:
     int a1;
     A()
    {
    }
};


class B: public A
{
    public:
    int b1;
    B()
    {
    }
};


int main()
{
     B tempb;
     A tempa;
     A * ptempa;
     ptempa = &tempb;

     std::cout << typeid(tempb).name() << std::endl;
     std::cout << typeid(tempa).name() << std::endl;
     std::cout << typeid(*ptempa).name() << std::endl;

     return 0;
}

Он всегда печатает:

Класс Б Класс А Класс А

Я использую VS2010 для своего проекта.


person user2600393    schedule 09.08.2013    source источник
comment
Он ведет себя так же, используя Clang 4.2. Я согласен, что это выглядит неправильно. Из определения документации typeid дает тип того, на что указывает, а не тип указателя. Извините, это не поможет. Моральная поддержка...   -  person David Elliman    schedule 09.08.2013


Ответы (3)


Объект, на который он указывает, должен быть полиморфным, чтобы это работало так, как вы ожидаете. Если бы у A было virtual методов, ваш код работал бы так, как ожидалось, например, добавляя виртуальный деструктор, который я демонстрирую здесь, используя gcc< /а>.

Цитата из раздела проект стандарта C++ 5.2.8 Параграф 2 Идентификация типа гласит:

Когда typeid применяется к выражению glvalue, тип которого является типом полиморфного класса (10.3), результат ссылается на объект std::type_info, представляющий тип наиболее производного объекта (1.8) [...]

Это относится к случаю, когда у нас есть метод virtual, в вашем случае у вас нет полиморфного типа, поэтому применяется параграф 3:

Когда typeid применяется к выражению, отличному от значения gl полиморфного типа класса, результат ссылается на объект std::type_info, представляющий статический тип выражения.

Таким образом, вы получите обратно тип static, который равен A.

Для полноты раздела 10.3 Виртуальные функции говорится:

Виртуальные функции поддерживают динамическое связывание и объектно-ориентированное программирование. Класс, который объявляет или наследует виртуальную функцию, называется полиморфным классом.

person Shafik Yaghmour    schedule 09.08.2013

Проблема в том, что A не имеет виртуальных функций, поэтому не считается полиморфным типом. В результате typeid ищет объявленный тип указателя, а не фактический тип объекта, на который он указывает.

person Pete Becker    schedule 09.08.2013
comment
Ахам. Хорошо знать! (И вы были правы, dynamic_cast<> даже не компилируется. - person ; 09.08.2013
comment
По крайней мере, любой класс, предназначенный для наследования, должен иметь свой виртуальный dtor. Так что я бы назвал дизайн OP неправильным. - person KitsuneYMG; 09.08.2013
comment
@KitsuneYMG - std::iterator разработан для получения от виртуального деструктора и не имеет его. Так и должно быть. - person Pete Becker; 26.09.2013
comment
@PeteBecker Я исправлен. Если ваш класс полностью исключен из сгенерированного кода и не участвует в макете, потому что он пустой, тогда да, вам не нужен виртуальный dtor. - person KitsuneYMG; 26.09.2013

Подумав об этом во время стрижки газона... Стрелка не может знать, на какой объект она указывает. Информация о типе сохраняется вместе с указателем и не изменяется при указании на производный класс (B). Таким образом, вам нужно приведение типов, чтобы изменить тип указателя, и вывод будет таким, как ожидалось.

person David Elliman    schedule 09.08.2013