我有一个工厂方法类,它生成“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;
由于
答案 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
答案 3 :(得分:1)
如果您只需要转换指针,则不必创建自己的类型标识符。只需使用dynamic_cast
转换指针即可。如果类型不匹配,您将获得一个空指针,您可以尝试其他类型。或者,您可以直接比较指针的typeid
和每个目标类型的typeid
。
当然,不必进行这种运行时类型搜索就更好了。