对于我的碰撞代码,我认为如果每个实体都覆盖并定义了自己与任何其他实体的交互,那将是很好的。所以,我试图实现这个:
Entity.h:
class Bullet;
class Person;
class Entity
{
public:
Entity();
~Entity();
virtual void resolveCollision(Entity &other);
virtual void resolveCollision(Bullet &other);
virtual void resolveCollision(Person &other);
};
Entity.cpp:
void Entity::Entity() {}
void Entity::~Entity() {}
void Entity::resolveCollision(Entity &other) {
std::cout << "collided entity with entity" << std::endl;
}
void Entity::resolveCollision(Bullet &other) {
std::cout << "collided entity with bullet" << std::endl;
}
void Entity::resolveCollision(Person &other) {
std::cout << "collided entity with person" << std::endl;
}
Person.h:
#include "Entity.h"
class Person :
public Entity
{
public:
Person();
~Person();
void resolveCollision(Entity &other) override;
void resolveCollision(Bullet &other) override;
void resolveCollision(Person &other) override;
};
Person.cpp:
Person::Person() {}
Person::~Person() {}
void Person::resolveCollision(Entity &other) {
std::cout << "collided person with entity" << std::endl;
}
void Person::resolveCollision(Bullet &other) {
std::cout << "collided person with bullet" << std::endl;
}
void Person::resolveCollision(Person &other) {
std::cout << "collided person with person" << std::endl;
}
Bullet.h(几乎是Person.h的复制品):
#include "Entity.h"
class Bullet :
public Entity
{
public:
Bullet();
~Bullet();
void resolveCollision(Entity &other) override;
void resolveCollision(Bullet &other) override;
void resolveCollision(Person &other) override;
};
Bullet.cpp(几乎是Person.cpp的复制品):
Bullet::Bullet() {}
Bullet::~Bullet() {}
void Bullet::resolveCollision(Entity &other) {
std::cout << "collided bullet with entity" << std::endl;
}
void Bullet::resolveCollision(Bullet &other) {
std::cout << "collided bullet with bullet" << std::endl;
}
void Bullet::resolveCollision(Person &other) {
std::cout << "collided bullet with person" << std::endl;
}
最后,main.cpp:
#include "Bullet.h"
#include "Person.h"
#include <typeinfo>
int main()
{
std::vector<std::shared_ptr<Entity>> entities;
entities.push_back(std::shared_ptr<Person>(new Person()));
entities.push_back(std::shared_ptr<Bullet>(new Bullet()));
std::cout << typeid(entities[0]).name() << std::endl;
std::cout << typeid(*entities[0]).name() << std::endl;
std::cout << typeid(entities[1]).name() << std::endl;
std::cout << typeid(*entities[1]).name() << std::endl;
(*entities[0]).resolveCollision(*entities[1]);
Person().resolveCollision(Bullet());
return 0;
}
由于某些奇怪的原因,控制台输出以下内容:
class std::shared_ptr<class Entity>
class Person
class std::shared_ptr<class Entity>
class Bullet
collided person with entity
collided person with bullet
所以它似乎认识到* entities [1]是一个类Bullet,但由于某种原因,它调用Person :: resolveCollision(Entity)而不是Person :: resolveCollision(Bullet),即使它们的实例类和做同样的事情会导致玩家和子弹之间的碰撞。我该怎么做才能造成这种情况?前向声明会导致这种情况吗?
谢谢!
答案 0 :(得分:3)
电话
(*entities[0]).resolveCollision(*entities[1]);
在编译时解析为Entity::resolveCollision(Entity &other);
。凭借virtual
函数调度机制,调用在运行时被调度到Person::resolveCollision(Entity &other);
。但是,动态调度系统不会根据Person::resolveCollision(Bullet &other);
的运行时信息将调用更改为other
。这需要double dispatch system,这不是语言的一部分。
答案 1 :(得分:0)
为了获得所需的行为,请使用以下代码:
auto bulletPtr = std::dynamic_pointer_cast<Bullet>(entities[1]);
if(bulletPtr)
{
entities[0]->resolveCollision(bulletPtr);
}
实体[0]的resolvecollision将调用Person的resolveCollision,因为该函数是虚拟的并且在派生类中被覆盖。 c ++运行时没有任何线索,实体[1]实际上是一个bulletPtr,所以你必须动态地将其抛弃。您必须检查dynamic_pointer_cast返回的指针的有效性。