在C++中,当对象关系不直观时,如何重用代码?
In C++, how to reuse the code when object relationship isn't intuitive?
如果这有点含糊,但是我不知道如何在以下情况下重复使用代码。我正在使用C 。
该程序是一个简单的模拟,并且在游戏中有一些不同的内容。
struct StupidBug;
struct SmartBug;
struct Plant;
struct Mammal;
这些事情中的每一个都有一组他们能够做的东西。
struct StupidBug
{
// Can walk,
// Can eat,
// Can see surroundings,
// Can spawn,
};
struct SmartBug
{
// Can walk,
// Can eat,
// Can see surroundings,
// Can see extended surroundings,
// Can spawn,
};
struct Plant
{
// Can spawn
// Can see surroundings
};
struct Mammal
{
// Can walk,
// Can eat,
// Can see surroundings,
// Can see extended surroundings,
};
这些生命形式之间的功能有很多重叠,但我不知道如何在它们之间共享代码。我想不出所有这些适当的继承形式。我尝试了构图,沿着:
的方式做点什么。struct AbilityToWalk
{
void walk(position, direction)
{
// walk code
}
};
struct StupidBug
{
AbilityToWalk walk;
// other abilities
};
struct SmartBug
{
AbilityToWalk walk;
// other abilities
};
// etc...
,但步行功能依赖于所谓的任何东西的位置。将生命形式的位置传递给了自己的会员功能,这感觉很奇怪,总体上感觉就像是一个非常笨拙的解决方案。
我不确定如何处理这种情况。有没有办法这样做直觉和优雅?我是否缺少相当明显的东西?
您可以实现这样的混合系统:
struct Walker
{
virtual void walk();
};
struct Spawner
{
virtual void spawn();
};
struct Seer
{
//seeing extended surroundings could be a specialized version of this
virtual void see();
};
struct Eater
{
virtual void eat();
};
struct Plant : Spawner, Seer
{
//inherit default see function
void spawn() override; //override spawn function
};
这样,您可以获得代码重复使用和界面的精细粒度,让您做以下操作:
std::vector<std::unique_ptr<Walkers>> walkers;
walkers.push_back(std::make_unique<Mammal>());
//...
for (auto&& walker : walkers) walker->walk();
class AbilityToWalk
{
public:
AbilityToWalk(Type& position)
: mPosition(position){}
void walk(Type direction)
{
walk(mPosition, direction);
}
private:
void walk(Type& position, Type direction)
{
// walk code
}
private:
Type& mPosition;
};
struct StupidBug
{
StupidBug():walk(mPosition){}
AbilityToWalk walk;
Type mPosition;
// other abilities
};
我不是要说组成比继承更优选。
我只是想回答奥里格纳尔问题的这一特定部分:
但是步行功能依赖于任何正在调用的位置 它。将生命形式的位置传给自己的成员感到很奇怪 功能,总体感觉就像是一个非常笨拙的解决方案。
我正在添加此答案,主要是为解决方案的完整解释,以及其他任何带有类似问题的人。
我使用了塔尔坦拉玛(Tartanllama)的类似混合蛋白的系统的方法。每种能力都可以获得自己的阶级,生命形式继承了所需的所有能力。
但是,仍然存在一个问题,即能够访问生命形式中包含的某些值的能力。
class Mover
{
public:
virtual void move(Vec2 direction)
{
/*the problem*/
Vec2 newPos = position + direction;
position = newPos;
}
};
class DumbBug : public Mover
{
public:
/*the problem*/
Vec2 position;
DumbBug(Vec2 pos)
: position(pos)
{}
};
在Mixin中创建一个参考变量,并将其等于构造函数中的生命形式位置,如用户3528438所建议的,不起作用,创造了令人困惑的行为。
事实证明,解决此问题的解决方案很简单:纯虚拟Getters/setters。
class Mover
{
public:
virtual void move(Vec2 direction)
{
/*the solution*/
Vec2 newPos = get_position() + direction;
set_position(newPos);
}
/*--- the solution -------------------*/
virtual Vec2 get_position() = 0;
virtual void set_position(Vec2 pos) = 0;
};
class DumbBug : public Mover
{
private:
Vec2 position;
public:
DumbBug(Vec2 pos)
: position(pos)
{}
/*- the solution -------------------*/
virtual Vec2 get_position() {
return position;
}
virtual void set_position(Vec2 pos) {
position = pos;
}
};
纯虚拟功能迫使您在生命形式的类别中定义它们,允许混合蛋白访问其所需的东西,并可以在许多不同的生命形式上重复使用。
我认为该解决方案足够直观且可重复使用,因此我将继续前进。
我意识到这个问题有点含糊,为此表示歉意,但仍然谢谢大家的帮助。
- 函数何时会在c++中包含stack_Unwind_Resume调用
- Python中的for循环与C++有何不同
- 如何将C++闭包与变量参数同时重用——类似于JavaScript
- 在C++中释放内存期间,迭代器与指针有何不同
- 重用对象与创建新对象
- 标准对此指向成员函数类型模板参数有何说明?是我的代码有误,还是 MSVS 16.6 有问题?
- 如何重用 http::beast::flat_buffer 和 http::response?
- 数组对象的生存期是否在重用其元素存储时结束?
- 类中的 C++ int 被设置为值,似乎不知从何而来
- -fvisibility-inline-hidden 与 gcc 中的 -fvisibility=hidden 有何不同
- 提升 Websocket 并io_context可重用性,以实现连接的可重新建立性
- 重用字符串流而不重新分配
- 通过放置 new 重用数据成员存储
- 在 While 循环中重用对象的多线程
- std::vector::assign/std::vector::operator=(const&) 是否保证在"this"中重用缓冲区?
- 在自定义类型图中重用 SWIG 映射
- 重用字符数组和 cin.getline
- OpenCL 重用具有不同定义 ( -D ) 的cl_kernel
- 具有许多派生类的可重用类的良好设计
- 在C++中,当对象关系不直观时,如何重用代码?