Fig*_*wig 3 c++ templates components
我正在尝试编写一个 Unity 风格的获取组件方法。这是我到目前为止的代码。它会编译,但会返回它找到的第一个组件,而不是正确的组件。我认为我使用 static_cast 是错误的。有什么更好的方法来做到这一点?请注意,我不想对组件类型进行硬编码,我希望能够编译此引擎并使用从 Component 继承的任何内容以便能够使用此系统。另请注意,每个组件都需要作为其自身返回,而不是组件*,因为这会隐藏子功能。
compStruct.components 是组件 *s 的向量。
template <typename CompType>
inline CompType getComponent()
{
for(Component * currComp : compStruct.components)
{
if (static_cast<CompType>(currComp)!= nullptr)
{
return static_cast<CompType>(currComp);
}
}
return nullptr;
}
Run Code Online (Sandbox Code Playgroud)
这是通用组件的示例
#pragma once
#include "Component.h"
#include "Animation2D.h"
class AnimationComponent : public Component
{
public:
AnimationComponent(GameObject*x) :Component(x) {}
~AnimationComponent() {}
void stepAnimation(double delta);
//add overload for 3d animations
int addAnimation(Animation2D);
void setAnimation(int);
private:
};
Run Code Online (Sandbox Code Playgroud)
以及组件基类:
#pragma once
class GameObject;
class Component
{
public:
Component(GameObject * h) { host = h; }
virtual ~Component() {}
GameObject* getHost() { return host; }
protected:
GameObject * host = nullptr;
};
Run Code Online (Sandbox Code Playgroud)
关于 存在一些根本性的误解static_cast:它只会进行强制转换,并且您有责任确保强制转换的指针实际上指向目标类型的对象。static_cast如果源指针已经是其自身,则只会返回空指针,但绝不会在类型不匹配时返回!
class B { /*...*/ };
class D1 : public B { };
class D2 : public B { };
D1 d1;
B* b = &d1;
D2* d2 = static_cast<D2*>(b);
Run Code Online (Sandbox Code Playgroud)
d2将是一个指向 d1 的指针(在某些涉及多重继承的情况下,可能会有一个偏移量),但对后者的数据的解释完全不同(除非D1和D2是布局兼容的),你可能会陷入地狱!
首先,我个人更喜欢修改后的签名:
template <typename CompType>
inline CompType* getComponent();
// ^
Run Code Online (Sandbox Code Playgroud)
它允许像getComponent<SomeType>()而不是那样调用您的函数getComponent<SomeType*>(),此外它还允许在函数体内使用指针,这更清晰,请参阅下面我适当调整的代码。
那么你真正需要的是dynamic_cast(根据我的个人喜好稍微调整你的代码......):
CompType* result = nullptr; // pointer: see above!
for(Component * currComp : compStruct.components)
{
result = dynamic_cast<CompType*>(currComp);
if(result)
break;
}
return result;
Run Code Online (Sandbox Code Playgroud)
编辑:赶上Nshant Singh的评论:
dynamic_cast实际上是相当昂贵的。
另一种方法可以是unordered_map,替换您的向量(如何设置的示例可以在type_index文档中找到;当然,您可以放置对象而不是字符串......)。那么你的查找可能如下所示:
auto i = map.find(std::type_index(typeid(CompType));
return i == map.end() ? nullptr : static_cast<CompType*>(i->second);
// now, you CAN use static cast, as the map lookup provided you the
// necessary guarantee that the type of the pointee is correct!
Run Code Online (Sandbox Code Playgroud)