如何在C ++中删除与typeid()。name()关联的数字?

时间:2013-05-04 23:50:18

标签: c++ casting typeid

我有一个工厂方法类,它生成“Items”并返回指向它创建的Item的指针。

我派生了Item的类。例如,物品可以是“武器”“消耗品”或“盔甲”。

我需要检测创建了哪种类型的Item,以便我可以将Item正确地转换为该类型。我做了一些测试线,看起来它正在做我想要的,除了添加与该类型相关的数字。

实施例

我有这条线:

cout << "Type Created: " << typeid(pItem).name() << endl;

返回基类Item,但会显示:“4Item”

然后我将其改为:

cout << "Type Created: " << typeid(*pItem).name() << endl;

哪个会给我正确的派生类型,但也会输入这个数字。所以我得到了类似“5Armor”的东西

为什么pItem会返回基类?为什么它返回类型的int?如何删除int?

做出我想要的解决方案 - 以“作弊”的方式:

            string type;
            string returnedType = typeid(*pItem1).name();
            for (int i=1; i < returnedType.length(); i++){
                    type.push_back(returnedType[i]);
            }
            cout << "type: " << type << endl;

由于

4 个答案:

答案 0 :(得分:8)

typeid返回const std::type_info&std::type_info类型有一个名为name的函数,它返回基础类型名称的实现定义的字符串表示形式。关于这个函数将返回的内容绝对没有保证 - 它不必返回一个看起来像任何原始程序中类型名称的字符串,并且可以根据它想要装饰它。 / p>

如果你需要跟踪你创建的类型的名称,我建议你只需要在你的层次结构中添加一个像这样的虚函数:

virtual std::string getType() const = 0;

这个函数可以返回一个很好的,人类可读的类型表示,保证以你想要的方式运行(因为你负责编写它)。

希望这有帮助!

答案 1 :(得分:4)

您可能不应该使用类型代码和切换/向下转换。相反,将特定于对象的代码放入虚拟方法或(根据手头的问题)使用访问者模式。您当前的方法最终可能看起来像这样:

int price = 0;

if (obj->get_type_str() == "armor")
{
    price = 1000 + ((Armor *)obj)->get_durability() * 100;
}
else if (obj->get_type_str() == "ninjasword")
{
    price = 5000 * ((NinjaSword *)obj)->get_damage();
}
else if (obj->get_type_str() == "bfg")
{
    price = 20000;
}

shop->show_price(price);

问题是,这不是很可扩展的。它不会像对象一样定义对象的价格,而是围绕着代码。更好的方法是提供一个虚拟方法get_price(),它可以做到这一点:

class GameObject
{
public:
    virtual ~GameObject() {}
    virtual int get_price() const = 0;
};

class Armor: public GameObject
{
public:
    virtual int get_price() const
    {
        return 1000 + durability * 100;
    }

private:
    int durability;
};

class NinjaSword: public GameObject
{
public:
    virtual int get_price() const
    {
        return 5000 * damage;
    }

private:
    int damage;
};

class Bfg: public GameObject
{
public:
    virtual int get_price() const
    {
        return 20000;
    }
};

现在,特定于对象的代码保留在对象中,前面的代码示例变为:

shop->show_price(obj->get_price());

如果相关代码实际上不属于该对象,则可能是Visitor模式的情况。

答案 2 :(得分:2)

我使用g ++也遇到了这个问题。现在严格回答你的问题而无意指出什么是最好的方法,还有另一种处理这种情况的方法。

以下是您的复制/粘贴示例:

创建一种类型的,如MyType.h

#ifndef __MYTYPE_H__
#define __MYTYPE_H__
class MyType {
};
#endif

和一个main.cpp文件,如下所示:

#include <cxxabi.h>
#include <iostream>
#include <typeinfo>

#include "MyType.h"

template <typename T> char* get_typename(T& object)
{
    return abi::__cxa_demangle(typeid(object).name(), 0, 0, 0);
}

int main(int argc, char ** argv)
{
    MyType my_type;

    std::cout << get_typename(my_type) << std::endl;

    return 0;
}

这将输出:MyType

我根据此post的答案找到了这个解决方案,并将我带到了article

答案 3 :(得分:1)

如果您只需要转换指针,则不必创建自己的类型标识符。只需使用dynamic_cast转换指针即可。如果类型不匹配,您将获得一个空指针,您可以尝试其他类型。或者,您可以直接比较指针的typeid和每个目标类型的typeid

当然,不必进行这种运行时类型搜索就更好了。