我正在编写一款 2d 游戏,希望从一开始就做好。我不太确定如何解决多重继承和强制转换。
例如,假设我有一个游戏世界。我创建了一个名为 Environment 的类,所有对象都将继承该类。
现在,如果我创建另一个名为 Brick 和 Ground 的类,这两个类将从环境中继承功能。现在假设我希望能够在接触 Brick 时爆炸,但地面类永远不会使用它,因此在环境类中创建一个类似的函数并使其成为虚拟的是一种浪费。
所以我虽然,也许如果我将环境对象转换回派生类并从那里调用它的函数:(下面只有一个例子来演示虽然过程)
#include <iostream>
#include <string>
#include <vector>
#include <limits>
class Environment
{
protected:
std::string name;
int health;
int damage;
public:
Environment(std::string _name)
{
this->name = _name;
}
virtual std::string GetType() = 0;
std::string GetName()
{
return this->name;
}
void Spawn()
{
std::cout << this->name << ": Spawning object..." << std::endl;
}
int GetHealth()
{
return this->health;
}
void TakeDamage(int _damage)
{
this->health-=_damage;
}
virtual void Update() = 0;
virtual void Render() = 0;
virtual ~Environment(){}
};
class Ground : public Environment
{
private:
public:
Ground(std::string _name) : Environment(_name)
{
}
std::string GetType()
{
return "Ground";
}
void Update()
{
std::cout << "Updating: " << this->name << std::endl;
}
void Render()
{
}
};
class Brick : public Environment
{
private:
public:
Brick(std::string _name) : Environment(_name)
{
this->name = "Brick Ansikte";
this->health = 100;
}
std::string GetType()
{
return "Brick";
}
void Update()
{
std::cout << "Updating: " << this->name << std::endl;
}
void Render()
{
}
void Explode()
{
std::cout << "Exploding BRICK" << std::endl;
}
};
int main()
{
std::vector<Environment*> listEnvironment;
listEnvironment.push_back(new Ground("Ground fool"));
listEnvironment.push_back(new Brick("Ground tun"));
for(auto& env : listEnvironment)
{
std::cout << "HP: " << env->GetHealth() << std::endl;
env->Spawn();
env->Update();
if (env->GetType() == "Brick")
{
std::cout << "BRICK TYPE WAS FOUND, DYNAMIC CAST" << std::endl;
static_cast<Brick*>(env)->Explode();
}
delete env;
}
listEnvironment.empty();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
return 0;
}
这个解决方案是好是坏?或者我应该创建另一个基本助手类来保存游戏中可能发生的所有不同类型的 Action 吗?比如爆炸、反弹等等?
最好的问候 尼洛
最佳答案
有两种解决方法:
使用
dynamic_cast
:if (Brick* brick = dynamic_cast<Brick*>(env)) { std::cout << "BRICK TYPE WAS FOUND, DYNAMIC CAST" << std::endl; brick->explode(); }
将另一个方法添加到
Environment
中,命名为MaybeExplode
(这实际上是一个非常糟糕的名字,但我真的想不出更好的名字):virtual void MaybeExplode() {}
现在,在
Brick
中覆盖它:void MaybeExplode() { std::cout << "Exploding BRICK" << std::endl; }
然后在
for
循环中无条件地调用MaybeExplode
:... env->Spawn(); env->Update(); env->MaybeExplode(); delete env;
这不是浪费。这确实是 OO 设计的方式。要求爆炸的人不知道 什么
env
是什么。此外,
dynamic_cast
实际上是 slower than a virtual function ,所以,如果有的话,你当前的版本是更多浪费。
关于c++ - 继承和转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29951502/