![](/img/trans.png)
[英]Using typeid in an abstract base class to auto generate derived class names. How to get desired results?
[英]Using typeid to get name of derived class
我正在创建一个资源管理器,它接受从类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
语句产生'Texture'?
指针的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
对象本身来进行运行时类型识别。
如果表达式是多态类对象的glvalue,则typeid
运算符只能返回表达式的动态类型 。
如果一个类直接或在其一个基础中定义至少一个虚拟成员函数,则该类是多态的 。
由于您的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'
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.