【发布时间】:2015-05-04 20:38:29
【问题描述】:
我正在处理基类实体,我希望它的派生类(玩家、敌人、子弹)调用 collideWith()
我试图让 Entity 的 collideWith() 的派生函数工作,但是,基本版本总是被调用,它恰好是空的,即使我删除了关键字 virtual
基类实体
virtual void collideWith(Entity*);
// Right now the derived classes of collideWIth are not being called,
// even with the virtual removed
及其函数,在碰撞检查期间总是被调用
void Entity::collideWith(Entity*){
}
具有 collideWith 函数的派生类,没有 virtual 关键字 这些在碰撞检查期间永远不会被调用
void Player::collideWith(Bullet*)
void Player::collideWith(Enemy*)
void Enemy::collideWith(Bullet*)
void Enemy::collideWith(Player*)
void Bullet::collideWith(Player*)
void Bullet::collideWith(Enemy*)
检查碰撞的功能 p 和 q 指向 EntityList 中的 Entity*,其中包含其派生类 玩家、敌人和子弹
void SceneGame::checkCollisions(){
populateGrid();
// Right now I am unable to get the collision detection to work!
for (auto i = 0; i < gridBox.slicesX; ++i){
for (auto j = 0; j < gridBox.slicesY; ++j){
if (gridBox.cell[i][j].nEntities < 2) continue;
for (auto k = 0; k < gridBox.cell[i][j].nEntities; ++k){
for (auto l = 0; l < gridBox.cell[i][j].nEntities; ++l){
// Set up the pointers and compare them
auto p = gridBox.cell[i][j].items[k];
auto q = gridBox.cell[i][j].items[l];
if (p == q) continue; // we do not want the same pointer
if (p->getGlobalBounds().
intersects(q->getGlobalBounds() )){
// Do a series of collisions depending on the specific entities
/*
However, I end up always calling the BASE function of collideWith
instead of the derived types (Player, Enemy, Bullet, etc.)
*/
p->collideWith(q);
}
}
}
}
}
}
【问题讨论】:
-
重载是根据参数的静态类型而不是动态类型来选择的。
-
这里重要的是类接口。您的问题是基类引用
Entity,派生类引用Player等。您要么需要基类为每个派生类型提供virtual方法,要么以其他方式实现Double Dispatch。 -
基类的 collideWith(Entity*) 有 virtual 关键字,所以它的派生类可以重新定义它,例如 Player::collideWIth(Bullet*)
-
参见例如:stackoverflow.com/questions/12582040/…,从中您会看到这个问题实际上是重复的。
-
正如@OliverCharlesworth 所说,
virtual不适用于参数,而仅适用于调用对象。
标签: c++ inheritance virtual derived-class base-class