Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用typeid获取派生类的名称_C++ - Fatal编程技术网

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'