-1

为了我自己的理解,我已经实现了以下程序。但是我看到 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.

我期待程序中指定的类名。

非常感谢。

4

2 回答 2

3

type_info::name()外观没有要求。

typeid表达式的结果是静态类型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

后两者向您表明,甚至不能依赖名称不同。

于 2013-04-17T05:47:28.347 回答
2

如果您对“解构”名称感兴趣,g++ 有一个特定于编译器的函数来执行此操作。

您可以在http://gcc.gnu.org/onlinedocs/libstdc++/manual/ext_demangling.html中找到一个示例

于 2013-04-17T06:28:31.297 回答