所以我正在学习C ++并希望编写一个实体组件系统。为此,我需要知道组件将其添加到实体时的类型。在java中我会做这样的事情:
Class<?> someClass = myComponent.class;
我能用C ++做些什么吗?我尝试过typeid(myComponent),但在这种情况下不起作用。
ExtComponent* extended = new ExtComponent();
Component* base = dynamic_cast<Component>(extended);
std::cout << typeid(base).name();
这会返回“类组件”,但我希望在这种情况下返回“类ExtComponent”。我该怎么做。
答案 0 :(得分:6)
如果我理解正确,你想获得动态类型的对象。 (不是变量本身的类型,而是变量(真正)指的是什么)
Typeid将起作用,因为:
N3337 5.2.8 / 2:
当typeid应用于glvalue表达式,其类型为多态类类型(10.3)时,结果引用 到std :: type_info对象,表示最派生对象的类型(1.8)(即动态 glvalue引用[...]
的类型
所以,只需添加一些虚拟功能(可选择虚拟基类),他们就会做你想做的事。
此外,您必须将typeid
应用于对象,而不是指针(因为这会为指针返回type_info
,而不是对象):
Base *b = new Base;
...
typeid(*b); //not typeid(b)
答案 1 :(得分:2)
处理类型时,必须在编译时解决所有问题。您无法在运行时解决它们。这就是C ++的工作原理。要做一些改变表达式类型的事情,你必须处理模板。
如果我们想创建一个存储各种类型实例的容器,你需要一种方法来记住它是哪种类型。由于模板实例化了一个不同的函数,每个函数都有自己的地址,我们可以用它来为类型生成一个唯一的id:
adding-charts
现在,您可以使用它以安全的方式存储和检索。在这里,我将使用template<typename>
void type_id(){}
using type_id_t = void(*)();
,但如果您无法访问C ++ 17功能,则可以将其替换为std::any
。
boost::any
你走了。您可以像这样试用您的实体:
struct Entity {
template<typename T>
void assign(T component) {
components[type_id<T>] = component;
}
template<typename T>
T& retrieve() {
return std::any_cast<T>(components[type_id<T>]);
}
private:
std::map<type_id_t, std::any> components;
};
这是实体的垃圾和简单实现。通常,您尝试将实体和组件保存到内存中,并使用实体管理器管理它们的生命周期。