san*_*e11 5 c++ pointers casting base-class derived-class
我有各种类型的碰撞器类(SphereCollider、AABBCollider 等),它们都继承自基类 Collider。我使用指向基类的指针将它们存储在 std::vector 中。
std::vector<std::shared_ptr<Collider>> colliders;
Run Code Online (Sandbox Code Playgroud)
然后我有各种函数来确定对撞机是否彼此相交。
bool Colliding(const SphereCollider& colliderOne, const SphereCollider& colliderTwo);
bool Colliding(const AABBCollider& colliderOne, const AABBCollider& colliderTwo);
bool Colliding(const AABBCollider& colliderOne, const SphereCollider& colliderTwo);
bool Colliding(const SphereCollider& colliderOne, const AABBCollider& colliderTwo);
Run Code Online (Sandbox Code Playgroud)
我的想法是简单地遍历碰撞器向量,然后将每个碰撞器与列表中的所有其他碰撞器进行比较。
for (unsigned int a = 0; a < colliders.size(); ++a)
{
for (unsigned int b = a + 1; b < colliders.size(); ++b)
{
// Store the two colliders we're current comparing
std::shared_ptr<Collider> colliderOne = colliders[a];
std::shared_ptr<Collider> colliderTwo = colliders[b];
// Somehow cast pointers back to correct derived type
// Check colliding
if(Colliding(*colliderOneDerived, *colliderTwoDerived))
{
// Colliding
}
}
}
Run Code Online (Sandbox Code Playgroud)
但是,要成功执行此操作,我需要将指针转换回正确的派生类型,以便调用正确的函数,但我不知道每次碰撞器都是什么类型。
基碰撞器类有一个 Type() 函数,它从基指针正确返回派生类型。
std::type_index Collider::Type() { return typeid(*this); }
Run Code Online (Sandbox Code Playgroud)
有没有办法可以使用它来将指针转换为正确的派生类型?
用于dynamic_pointer_cast获取派生类上的共享指针。nullptr如果派生类的类型错误,则返回指针。
std::shared_ptr<SphereCollider> sc = std::dynamic_pointer_cast<SphereCollider>(colliderOne);
Run Code Online (Sandbox Code Playgroud)
scnullptr如果colliderOne不是类型,则为SphereCollider。否则它将指向SphereCollider.
通过使用此方法,您可以实现动态调度。
更新:
下面是如何使用智能指针向下转型来实现动态调度的示例。
std::shared_ptr<SphereCollider> sc1, sc2;
std::shared_ptr<AABBCollider> aabc1, aabc2;
...
if (sc1 = std::dynamic_pointer_cast<SphereCollider>(colliderOne))
{
if (sc2 = std::dynamic_pointer_cast<SphereCollider>(colliderTwo))
Colliding(*sc1, *sc2);
else if (aabc2 = std::dynamic_pointer_cast<AABBCollider>(colliderTwo))
Colliding(*sc1, *aabc2);
...
}
else if (aabc1 = std::dynamic_pointer_cast<AABBCollider>(colliderOne))
{
if (sc2 = std::dynamic_pointer_cast<SphereCollider>(colliderTwo))
Colliding(*aabc1, *sc2);
else if (aabc2 = std::dynamic_pointer_cast<AABBCollider>(colliderTwo))
Colliding(*aabc1, *aabc2);
...
}
...
Run Code Online (Sandbox Code Playgroud)
如果您有许多不同类型的 Collider 类,则上面的代码可能不是很有效。它在类中执行线性搜索来执行调度。
通过向返回类名的 Collider 类添加一个字段,您可以连接两个类名来构建一个键。然后,您可以使用
std::unordered_map带有 lambda 的 an 作为关联值。lambda 将接收这两个参数std::shared_ptr<Collider>作为参数。它将执行向下转换并调用 Collider 函数。
如果您需要,我会显示代码。
| 归档时间: |
|
| 查看次数: |
1954 次 |
| 最近记录: |