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

Hab*_*bit 7 c++ casting typeid

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

我已经派生了Item类.例如,物品可以是"武器""消耗品"或"装甲".

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

例:

我有这条线:

cout << "Type Created: " << typeid(pItem).name() << endl;
Run Code Online (Sandbox Code Playgroud)

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

然后我改为:

cout << "Type Created: " << typeid(*pItem).name() << endl;
Run Code Online (Sandbox Code Playgroud)

哪个会给我正确的派生类型,但也会输入这个数字.所以我得到像"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;
Run Code Online (Sandbox Code Playgroud)

谢谢

tem*_*def 9

typeid返回一个const std::type_info&.该std::type_info类型具有一个调用的函数name,该函数返回基础类型名称的实现定义的字符串表示形式.关于这个函数将返回的内容绝对没有保证 - 它不必返回一个看起来像任何东西的字符串,就像原始程序中的类型名称一样,并且可以根据需要修饰它.

如果您需要跟踪您创建的类型的名称,我建议您只需将类似虚拟函数添加到您的层次结构中:

virtual std::string getType() const = 0;
Run Code Online (Sandbox Code Playgroud)

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

希望这可以帮助!

  • @Justin,Go在另一个编译器上运行它并观看它的刻录.问题是你对返回的内容没有发言权.每个编译器都会按照自己的意 对于每个编译器,此解决方案都可以得到保证. (2认同)
  • @Justin No for循环.`class Item {public:virtual std :: string GetName()const = 0; 在基类中,然后`类Armor:public Item {public:virtual std :: string GetName()const {return"Armor"; `Armor :: GetName()`的实现可以在头文件或cpp文件中."盔甲"课程. (2认同)

rbe*_*nto 7

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

这是一个复制/粘贴示例:

创建一个你的类型,比如 MyType.h

#ifndef __MYTYPE_H__
#define __MYTYPE_H__
class MyType {
};
#endif
Run Code Online (Sandbox Code Playgroud)

和一个 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;
}
Run Code Online (Sandbox Code Playgroud)

这将输出:MyType

我根据这篇文章中的一个答案找到了这个解决方案,这篇文章将我带到了这篇文章


oll*_*llb 4

您可能不应该为此使用类型代码和 switch/downcasts。相反,将特定于对象的代码放入虚拟方法中或(取决于手头的问题)使用访问者模式。您当前的方法最终可能看起来像这样:

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);
Run Code Online (Sandbox Code Playgroud)

问题是,这不是很可扩展。它不会随对象一起定义对象的价格,而是散布在代码中。更好的方法是提供一个虚拟方法 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;
    }
};
Run Code Online (Sandbox Code Playgroud)

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

shop->show_price(obj->get_price());
Run Code Online (Sandbox Code Playgroud)

如果相关代码并不真正属于该对象,则这可能是访问者模式的情况。