Получение неправильного имени класса при использовании typeid -

Для собственного понимания я реализовал приведенную ниже программу. Но я вижу, что имя класса, возвращаемое typeid, немного изменено. Я знал, что это могло быть из-за искажения имени, но включение extern C тоже не помогает.

Может ли кто-нибудь помочь мне понять, почему такое поведение, а также как его исправить?

версия g ++ - 4.7.0

#include <iostream>
#include <typeinfo>

using namespace std;

class Base
{
    public:
        virtual ~Base(){}
};

class Derive : public Base
{
    public:
        ~Derive(){}
};

class newBase
{
    public:
        ~newBase(){}
};

class newDerive : public newBase
{
    public:
        ~newDerive(){}
};

int main()
{
    Base base;
    Derive derive;
    Base *pBase;
    Base & rBase1 = base;
    Base & rBase2 = derive;

    newBase newbase;
    newDerive newderive;
    newBase *pNewBase;

    //Results with polymorphic class.
    pBase = &base;
    cout<<"Base class pointer pBase contains object of type "<<typeid(*pBase).name()            <<".\n";

    pBase = &derive;
    cout<<"Base class pointer pBase contains object of type "<<typeid(*pBase).name()<<".\n";

    cout<<"\nReference variable rBase1 referring to "<<typeid(rBase1).name()<<".\n";
    cout<<"Reference variable rBase2 referring to "<<typeid(rBase2).name()<<".\n";

    //Results with non-polymorphic class.
    pNewBase = &newbase;
    cout<<"\nBase class pointer pNewBase contains object of type "<<typeid(*pNewBase).name()<<".\n";

    pNewBase = &newderive;
    cout<<"Base class pointer pNewBase contains object of type "<<typeid(*pNewBase).name()<<".\n";

    return 0;
}

Output -
Base class pointer pBase contains object of type 4Base.
Base class pointer pBase contains object of type 6Derive.

Reference variable rBase1 referring to 4Base.
Reference variable rBase2 referring to 6Derive.

Base class pointer pNewBase contains object of type 7newBase.
Base class pointer pNewBase contains object of type 7newBase.

Я ожидал, что имя класса будет указано в программе.

Большое спасибо.


person tshah06    schedule 17.04.2013    source источник
comment
Вы могли бы сделать свой вопрос более полным, приведя пример имени, которое вы получили, и того имени, которое вы ожидали. Это все еще дубликат, который, вероятно, является причиной того, что dv.   -  person Captain Obvlious    schedule 17.04.2013
comment
@ user93353 - Я выполнил команду ./a.out | c ++ filter, но это тоже не помогло. Что-то мне еще не хватает? Спасибо. Капитан - Согласен, я должен был выдать результат. Отредактировал пост.   -  person tshah06    schedule 17.04.2013


Ответы (2)


Нет никаких требований к тому, как выглядит type_info::name().

Результатом typeid выражения является lvalue статического типа const std::type_info (18.7.1) и динамического типа const std::type_info или const name, где name - это определяемый реализацией класс, публично производный от std::type_info

Затем о std::type_info::name():

const char* name() const;

Возвращает: NTBS, определяемую реализацией.

[...]

NTBS - это просто сокращение для байтовой строки с завершающим нулем.

Другими словами: вы не должны полагаться ни на какое значение type_info::name().

Что вы на самом деле видите с g ++:

Эти имена являются искаженными именами, а реализация таких искаженных имен в g ++ основана на строки с префиксом длины, где каждая подстрока - это имя пространства имен плюс некоторая другая информация; но это в основном все.

Например:

unmangled: foo::bar::Frob
mangled:   3foo3bar4Frob

Пример для вашего компилятора:

#include <iostream>
#include <typeinfo>

namespace foo { namespace bar { 
    enum Frob {};
    class Frobnicate {};
    Frob frob;

    template <typename T> void Meh() { throw T(); }
} }

int main () {
    std::cout << typeid(foo::bar::Frob).name() << '\n'
              << typeid(foo::bar::Frobnicate).name()  << '\n'  
              << typeid(foo::bar::frob).name() << '\n'
              << typeid(foo::bar::Meh<int>).name() << '\n'
              << typeid(foo::bar::Meh<float>).name() << '\n'
    ;
}

Вывод для меня:

N3foo3bar4FrobE
N3foo3bar10FrobnicateE
N3foo3bar4FrobE
FvvE
FvvE

Последние два показывают вам, что нельзя даже полагаться на разные имена.

person Sebastian Mach    schedule 17.04.2013
comment
Спасибо, Френель. Как новичок, я просто подумал, что он должен возвращать имя типа, указанное в программе. Но теперь я думаю, что все ясно. Ваше объяснение помогло. Еще раз спасибо. - person tshah06; 17.04.2013
comment
Последние два показывают вам, что нельзя даже полагаться на разные имена. - И все же они разные. - person Christian Rau; 17.04.2013
comment
@ChristianRau: facepalm (править: пример уточнен) - person Sebastian Mach; 17.04.2013

Если вас интересует "разборчивость" имени, в g ++ есть для этого специфическая для компилятора функция.

Вы можете найти пример в http://gcc.gnu.org/onlinedocs/libstdc++/manual/ext_demangling.html

person Emilio Garavaglia    schedule 17.04.2013
comment
Думаю, это должен быть комментарий. - person Sebastian Mach; 17.04.2013
comment
@Emilio: Спасибо за ссылку. Я изменил свою программу, чтобы избежать искажения имен. - person tshah06; 17.04.2013