![](/img/trans.png)
[英]C++, using std::sort on a vector of class pointers - OR I can't name my functions properly
[英]I can't use subclass specific funcitons when I add them to a vector using parent class pointers
我正在尝试自己制作“外星人入侵者”游戏。 为了创建敌人和玩家,我创建了一个名为“实体”的类并创建了它的子类。 像Player,射击Enemy,IdleEnemy。 编码时,我意识到将它们收集在vector<Entity>
将使我的碰撞检测功能更容易。
在互联网上搜索后,我了解到这称为“对象切片”,并复制对象的任何基本部分。
所以最终版本变成了这个。
int main()
{
int BoardWidth = 50;
int BoardLength = 30;
vector<Bullet> bullets;
vector<Entity*> SpaceShips;
setup(SpaceShips, BoardWidth, BoardLength);
double ElapsedTime = 0;
int PreviousRoundSec = 0;
int PreviousRoundQSec = 0;
DrawGame(BoardWidth, BoardLength, SpaceShips, bullets);
int IsGameOver = 0;
auto start = chrono::steady_clock::now();
while(!IsGameOver)
{
// Updates EverySecond
if ((int)(ElapsedTime / 1000) > PreviousRoundSec)
{
PreviousRoundSec = (int)(ElapsedTime / 1000);
}
// Updates every quarter of a second
if ((int)(ElapsedTime / 250) > PreviousRoundQSec)
{
PreviousRoundQSec = (int)(ElapsedTime / 250);
}
// To keep time
auto end = chrono::steady_clock::now();
ElapsedTime = chrono::duration_cast<chrono::milliseconds>(end - start).count();
}
if (IsGameOver == 1)
{
// conjualations
}
else if (IsGameOver == 2)
{
// GameOver
}
return 0;
}
但是当我尝试使用一些特定于子类的函数时,我收到一个编译器错误,提示“类“实体”没有任何名为“射击”的成员。
我正在尝试练习类和多态性,所以我什至不知道这有解决方案,因为编译器无法知道此向量的哪个元素属于哪个子类。
如果需要,这也是我的类标题页。
class Entity
{
public:
int x;
int y;
int width;
int length;
int hp;
bool shooting;
public:
Entity(int x, int y, int width, int length, int hp, bool shooting): x(x), y(y), width(width), length(length), hp(hp), shooting(shooting) {}
};
class Bullet : public Entity
{
private:
char dir;
int ID;
public:
Bullet(int x, int y, char GivenDir, int GivenID) : Entity(x, y, 1, 1, 1, false) { dir = GivenDir; ID = GivenID; }
void Move();
void IfHit(vector<Entity>& SpaceShips);
void IfOut();
};
class Player : public Entity
{
private:
char action = 'a';
public:
Player(int x, int y, int hp) : Entity(x, y, 3, 2, hp, true) {}
void GetAction();
void Move();
void Shoot(vector<Bullet>& bullets);
bool IfHit(vector<Entity>& SpaceShips, vector<Bullet>& bullets);
};
class IdleEnemy : public Entity
{
public:
IdleEnemy(int x, int y, int hp) : Entity(x, y, 3, 2, hp, false){}
bool IfHit(Player* player, vector<Bullet> &bullets);
void Move(char HordDir);
};
class ShootingEnemy : public Entity
{
public:
ShootingEnemy(int x, int y, int hp) : Entity(x, y, 3, 2, hp, true) {}
void Shoot(vector<Bullet> &bullets);
bool IfHit(Player* player, vector<Bullet> &bullets);
void Move(char HordDir);
};
您需要在 C++ 中检查运行时多态性。 让我们来看看你怎么能做到这一点。 首先,您需要更改您的Entity
类接口。 您需要添加虚函数或纯虚函数。 我添加了纯虚函数;
class Entity
{
public:
int x;
int y;
int width;
int length;
int hp;
bool shooting;
public:
Entity(int x, int y, int width, int length, int hp, bool shooting) : x(x), y(y), width(width), length(length), hp(hp), shooting(shooting) {}
void virtual Move() = 0; // pure virtual function
void virtual IfHit() = 0; // pure virtual function
};
虚函数是可覆盖的函数。 此外,它们有实现,但当我们谈论纯虚函数时,它们只为类提供接口。 您需要在派生类中覆盖该函数。 当你实现你的派生类时,你需要这样做,
class Bullet : public Entity
{
private:
char dir;
int ID;
public:
Bullet(int x, int y, char GivenDir, int GivenID) : Entity(x, y, 1, 1, 1, false) { dir = GivenDir; ID = GivenID; }
void Move()override;
void IfHit();
void IfOut();
};
class Player : public Entity
{
private:
char action = 'a';
public:
Player(int x, int y, int hp) : Entity(x, y, 3, 2, hp, true) {}
void GetAction();
void Move();
void Shoot(vector<Bullet>& bullets);
void IfHit()override {//code};
};
class IdleEnemy : public Entity
{
public:
IdleEnemy(int x, int y, int hp) : Entity(x, y, 3, 2, hp, false) {}
void IfHit()override;
void Move()override;
};
class ShootingEnemy : public Entity
{
public:
ShootingEnemy(int x, int y, int hp) : Entity(x, y, 3, 2, hp, true) {}
void Shoot(vector<Bullet>& bullets);
void IfHit()override;
void Move()override;
};
这些函数可以内联或在源文件中实现。 此外,这些函数的一个重要点是返回值、函数签名和名称必须相同,除非您不使用协变返回类型。
正如在派生类中看到的那样,有些函数并不常见。 我知道你的问题,我该如何使用它:) 正如评论中提到的 ttemple,你需要使用dynamic_cast
运算符。
int main()
{
Entity* ptr = new ShootingEnemy{ 1,2,4 };
ptr->Move();
ptr->IfHit();
if (auto SE = dynamic_cast<ShootingEnemy*>(ptr))
SE->Shoot(...);
}
dynamic_cast
运算符是运行时转换运算符。 它将基类指针的类型转换为派生类。 这被称为向下转型。 此外,它还检查基类指针是否指向目标派生类。 如果dynamic_cast
操作以失败完成,则它返回null
并且if statement
变为失败。 通过这种方式,您可以使用运行时多态性和类成员函数。
顺便说一下,尽可能避免对象切片。 您正在丢失派生类属性。
为了更好地理解,请参考类dynamic_cast
编译器告诉你真相。 你有一个指向Entity
的指针,它的接口中显然没有Shoot
方法,所以你怎么可能在没有任何强制转换的情况下调用它?
您在这里尝试实现的动态多态背后的想法是关于拥有一个公共接口(您的基类, Entity
),在每个子类中都有特定的实现。 因此,公开可用的方法签名对于所有子类都是通用的,但不是实现。
从设计的角度来看,最ShootableEntity
方法是将Entity
重命名为ShootableEntity
并在其中声明一个纯虚拟Shoot
方法。 然后所有的子类都应该提供一些实现。
如果不是所有的人都实现了Shoot
,但你试图以这种方式一般地使用它们,也许你应该重新考虑这种方法,例如。 创建两个容器 - 用于可射击实体和不可射击实体。 然后,当迭代可射击实体(实际上是ShootableEntity
子类的类的ShootableEntity
,其中包含Shoot
声明)时,您可以毫无问题地在基类的指针上调用Shoot
。
但是,您的Entity
不代表任何通用接口。 所以,如果你试图利用多态(所以,你有一个指向基类的指针,但在该指针后面有一些具体的实例),这样的类对你没有任何好处。
其实doc本身就有很好的解释: http : //www.cplusplus.com/doc/tutorial/polymorphism/
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.