我正在创建一个资源管理器,它接受从类Resource
派生的类。我的问题是typeid(..)。name()返回错误的类名。
我想将像Texture这样的资源添加到这样的地图中:
typedef std::unordered_map<std::string, Resource*> ResourceMap;
我希望'class + counter'的名称是Resource的字符串/名称。不幸的是,所有内容最终都被称为P8Resource
,因为这些类派生自“资源”。确实是一个不合时宜的困境,但是typeid必须知道texture
是一个纹理,而不是资源。
class Resource {}; // abstract
class Texture : public Resource {};
Resource *texture = new Texture();
Texture *texture2 = new Texture();
typeid(texture).name(); // yields 'Resource'
typeid(texture2).name(); // yields 'Texture'
如何在不使用类型转换的情况下使第一个typeid
语句产生'纹理'?
答案 0 :(得分:16)
typeid
将始终是声明的类型,因为它是指针本身的真实类型。要知道指针指向的对象的实际类型,您需要取消引用指针以获取实际类型:http://ideone.com/FYmp79
#include <iostream>
#include <typeinfo>
using namespace std;
struct Resource {
virtual ~Resource() = default;
};
struct Texture : Resource {};
int main() {
Resource *resource = new Resource;
Resource *texture = new Texture;
cout << typeid(*resource).name() << endl; // yields 'Resource'
cout << typeid(*texture).name() << endl; // yields 'Texture'
return 0;
}
编辑:正如其他人所说,你需要使类具有多态性以获取运行时类型信息。
答案 1 :(得分:10)
我的问题是typeid(..)。name()返回错误的名称 类。
typeid(...).name()
仅用于调试或记录目的。正如http://en.cppreference.com/w/cpp/types/type_info/name所说:
不保证,特别是返回的字符串可以 对于几种类型是相同的,并且在相同的调用之间进行更改 程序
至于你的问题,
如何使第一个typeid语句在没有的情况下产生'Texture' 使用类型转换?
最安全,最简单,最正确的方法是将自己的虚拟名称功能添加到Resource
:
virtual std::string name() const = 0;
然后在每个子类中覆盖它以返回类的名称。
答案 2 :(得分:2)
首先,typeid
只能为多态类类型的值提供动态运行时类型标识。你的课程不是多态的。您需要在基类中至少有一个虚方法才能激活&#34;激活&#34; typeid
的动态行为。
其次,为了使用typeid
来确定多态对象的动态类型,你必须将应用于对象本身,而不是指向对象的指针(如你的代码)。
第三,name()
返回的值并不重要,不能用于任何实际目的。形式上,name()
每次只能返回一个空字符串。您必须使用(并比较)type_info
个对象本身来进行运行时类型识别。
答案 3 :(得分:0)
如果您使用的是Qt库,则可以使用元对象来区分资源实例。
class Resource : public QObject {
Q_OBJECT
}; // abstract
class Texture : public Resource {
Q_OBJECT
};
Resource *texture = new Texture();
Resource *resource = new Resource();
texture ->metaObject()->className(); // yields 'Texture'
resource ->metaObject()->className(); // yields 'Resource'