C++ 使用typeid获取派生类的名称
我正在创建一个资源管理器,它接收从类C++ 使用typeid获取派生类的名称,c++,C++,我正在创建一个资源管理器,它接收从类资源派生的类。我的问题是typeid(..).name()返回了错误的类名称 我想向贴图添加纹理等资源,如下所示: typedef std::unordered_map<std::string, Resource*> ResourceMap; 如何在不使用类型转换的情况下使第一个typeid语句产生“纹理” 我的问题是typeid(..).name()返回了错误的 班级 typeid(…).name()仅用于调试或记录目的。正如上面所说: 不提供
资源
派生的类。我的问题是typeid(..).name()返回了错误的类名称
我想向贴图添加纹理等资源,如下所示:
typedef std::unordered_map<std::string, Resource*> ResourceMap;
如何在不使用类型转换的情况下使第一个typeid
语句产生“纹理”
我的问题是typeid(..).name()返回了错误的
班级
typeid(…).name()
仅用于调试或记录目的。正如上面所说:
不提供任何保证,尤其是返回的字符串可以
多个类型相同,并且在相同类型的调用之间发生更改
节目
至于你的问题,
如何使第一个typeid语句在没有
使用类型转换
最安全、最简单、最正确的方法是将您自己的虚拟名称函数添加到资源中
:
virtual std::string name() const = 0;
然后在每个子类中重写它以返回类的名称。
typeid
指针的类型始终是声明的类型,因为这是指针本身的真实类型。要知道指针指向的对象的实际类型,需要取消对指针的引用以获得实际类型:
#包括
#包括
使用名称空间std;
结构资源{
virtual~Resource()=默认值;
};
结构纹理:资源{};
int main(){
资源*资源=新资源;
资源*纹理=新纹理;
cout首先,typeid
只能为多态类类型的值提供动态运行时类型标识。您的类不是多态的。为了“激活”typeid
的动态行为,基类中至少需要一个虚方法
其次,为了使用typeid
确定多态对象的动态类型,必须将其应用于对象本身,而不是对象指针(如代码中所示)
第三,name()
返回的值意义不大,不能用于任何实际目的。形式上,name()
每次只返回一个空字符串。您必须使用(并比较)type\u info
对象本身用于运行时类型标识。如果表达式是多态类对象的glvalue,则typeid
运算符只能返回表达式的动态类型
如果一个类直接或在它的一个基中定义了至少一个虚拟成员函数,那么它就是多态的
由于资源
类和派生类不满足此要求,typeid
运算符只能访问静态类型
要解决这个问题,以及在尝试删除指向此类资源的指针时将遇到的问题,请将析构函数设置为虚拟。如果您使用的是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'
为什么不创建一个名为name
的虚拟函数,该函数将返回一个字符串,其中包含您想要的类的信息?嗯?您不能,因为Resource
从未被实例化过???Resource
很可能还需要一个虚拟析构函数。我已经考虑过类似的问题;它可能是最乏味但最有效的“C++”没有java类似的反射。从正面看,这使得代码更加健壮和可预测。@布瑞恩:在OP的真正代码中,当然,他应该把它添加到他在这里发布的代码片段中。休息我确实有一个虚拟析构函数。谢谢大家!我不知道是谁否决了YO。你的答案,但我的问题也被否决了。我已经中和了你的否决票和其他答案,因为我知道你的两个答案都很有帮助。谢谢!
#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;
}
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'