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)
谢谢
typeid返回一个const std::type_info&.该std::type_info类型具有一个调用的函数name,该函数返回基础类型名称的实现定义的字符串表示形式.关于这个函数将返回的内容绝对没有保证 - 它不必返回一个看起来像任何东西的字符串,就像原始程序中的类型名称一样,并且可以根据需要修饰它.
如果您需要跟踪您创建的类型的名称,我建议您只需将类似虚拟函数添加到您的层次结构中:
virtual std::string getType() const = 0;
Run Code Online (Sandbox Code Playgroud)
这个函数可以返回一个很好的,人类可读的类型表示,保证以你想要的方式运行(因为你负责编写它).
希望这可以帮助!
我使用 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
我根据这篇文章中的一个答案找到了这个解决方案,这篇文章将我带到了这篇文章。
您可能不应该为此使用类型代码和 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)
如果相关代码并不真正属于该对象,则这可能是访问者模式的情况。