使用typeid获取派生类的名称
Using typeid to get name of derived class
我正在创建一个资源管理器,它接受从类Resource
派生的类。我的问题是typeid(..).name()返回错误的类名。
我想添加像纹理这样的资源到一个地图:
typedef std::unordered_map<std::string, Resource*> ResourceMap;
我想'类+计数器'的名称是资源的字符串/名称。不幸的是,所有东西最终都被称为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
语句产生"纹理"而不使用类型转换?
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;
}
编辑:正如其他人所说,您需要使类多态以获得运行时类型信息。
我的问题是typeid(..).name()返回错误的名称类。
typeid(...).name()
仅用于调试或日志目的。正如http://en.cppreference.com/w/cpp/types/type_info/name所说:
没有给出保证,特别是,返回的字符串可以是对于几种类型相同,并且在相同的调用之间更改程序。
关于你的问题,
我如何使第一个typeid语句产生'Texture'没有使用类型转换?
最安全、最简单和最正确的方法是在Resource
中添加自己的虚拟名称函数:
virtual std::string name() const = 0;
然后在每个子类中重写它以返回类名。
首先,typeid
只能为多态类类型的值提供动态运行时类型识别。你的类不是多态的。为了"激活"typeid
的动态行为,你需要在基类中至少有一个虚方法。
typeid
来确定多态对象的动态类型,您必须将它应用于对象本身,而不是对象的指针(如在您的代码中)。第三,name()
返回的值没有多大意义,不能用于任何实际目的。形式上,name()
每次都可以简单地返回一个空字符串。您必须使用(并比较)type_info
对象本身来进行运行时类型标识。
typeid
操作符只能返回表达式的动态类型,如果该表达式是多态类的对象的glvalue。
如果一个类直接或在它的一个基类中定义了至少一个虚成员函数,则该类是多态的。
由于Resource
类和派生类不满足此要求,typeid
操作符只能访问静态类型。
要解决这个问题,以及当您尝试delete
指向此类资源的指针时将遇到的问题,请将析构函数设置为virtual。
如果您正在使用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'
- 为什么使用 "this" 指针调用派生成员函数?
- 具有奇怪重复模板模式的派生类中的成员变量已损坏
- 在派生函数中指定void*参数
- 如何通过派生类函数更改基类中的向量
- 如何委托派生类使用其父构造函数?
- 如何使用单独文件中的派生类访问友元函数对象
- 派生类销毁的最佳实践是什么
- 如何使用基类指针引用派生类成员
- 派生类是否可以在抽象工厂设计模式中具有数据成员
- 使用基类指针创建对象时,缺少派生类析构函数
- 如何引用基类的派生类?
- 存储模板类型以强制转换回派生<T>
- 需要从 istream 和 ostream 派生 iostream
- 在 C++ 中用派生类型重写成员函数
- 具有多个类、派生类的C++正向声明
- 有没有一种"cleaner"的方法可以在指向基的指针向量中找到派生类的第一个实例?
- typeid.name 返回派生类类型之前的数字
- 使用typeid在派生类之间进行比较
- 如何使用typeid检查对象是哪个派生类
- 使用typeid获取派生类的名称