我正在构建一个组件系统,其中继承了抽象类型Component
以制作组件。到目前为止,我有可绘制的,物理的,可移动的和其他组件。一切似乎进展顺利,在Game
课程中我执行以下操作:
void Game::init()
{
pPlayer->addComponent(pMovable);
}
void Game::processEvents()
{
if (sf::Keyboard::isKeyPressed(sf::Keyboard::W))
pMovable->moveUp(2.f);
// etc..
pPlayer->setVelocity(pMovable->getVelocity());
}
void Game::update()
{
pPlayer->update(0);
}
void Game::play()
{
while (pWindow->isOpen())
{
// ...
processEvents();
}
}
到目前为止,组件系统非常简单。玩家的类型为Object
,每当我调用玩家的更新功能时,我也会调用对象的更新功能。这应该是自动化的,但将来会发生变化。真正的问题是:
pPlayer
仍然可以访问pMovable
的速度,即使它尚未添加pMovable
作为组件。这是有问题的,因为这意味着任何人都可以简单地从pMovable
获取速度,然后将其插入到对象中,而无需添加pMovable
作为其组件的一部分。现在,倾向于发生的事情是,由于没有可移动的组件来调节它,因此运动变得不受管理。我将这个组件的未经授权使用称为术语,并且我想开发一种方法,通过该方法,组件可以“拒绝”将其功能用于不属于它的对象。这个问题有很多解决方案,我需要一个有效且实用的解决方案。这是我的:
如果客户端尝试将组件功能分配给自己而不添加它,则抛出异常;
创建一个系统,通过该系统识别对象和组件,组件跟踪它所拥有的对象,并且对象跟踪它拥有的组件。因为这是一个多对多的关系,所以必须创建一个管理所有这些的中间类;它还避免了圆形标题包含。
让一个函数不是一个对象的一部分,只是'停用'。这将需要使用类似'componentAdded'的布尔值,并且所有函数都必须检查是否添加了组件,否则函数将不会执行应该执行的操作。
如果您有其他解决方案可以防止未经授权使用组件,请分享它们,因为我希望向其他人学习如何实现/或实现组件系统。
答案 0 :(得分:0)
您无法阻止特定类继承。它是一个全有或全无的命题:任何类都继承自基类或没有。
你可以期待的最好的是缩小界面。例如,您可能希望使用类Object
或Stationary_Object
来优化接口,而不是在函数中允许Enemy_Object
的后代。这使您可以编写任意Enemy_Object
并且不会采用Stationary_Object
(如树或墙)的函数。
编辑1:与朋友作弊
您可以通过将成员声明为私有并允许使用friend
类授予对特定类的访问权限来允许成员访问。问题是每当创建新类型的 friend 时,都需要修改包含数据的类。我相信这种friend
船的使用违背了可重用性的目的。
编辑2:检测所有权
我们假设我们有三个班级:
class Engine;
class Car
{
Engine car_engine;
};
class Boat
{
Engine boat_engine;
};
一个功能:
void Fix_Car_Engine(Engine& e)
{
}
C ++中没有方法让Fix_Car_Engine
知道它正在修理汽车引擎或船用引擎。该函数只知道它已被赋予通用引擎来修复(或者它只知道变量的常见引擎内容)。
通过改进或缩小界面可以缓解此问题:
class Car_Engine : public Engine;
class Boat_Engine : public Engine;
class Car
{
Car_Engine diesel_engine;
};
class Boat
{
Boat_Engine propellor_engine;
};
在上面的示例中,Engine类有两个特化:Car_Engine
和Boat_Engine
。 Car
现在有Car_Engine
成员,Boat
有Boat_Engine
成员。
现在可以创建功能以在特殊引擎上运行:
void fix_boat_engine(Boat_Engine& be);
void fix_car_engine(Car_Engine& ce);
fix_car_engine
现在只适用于汽车发动机。您可以说它适用于任何具有Car Engine的类(只要您传递Car Engine成员)。同样,fix_boat_engine
功能仅适用于船用发动机。
鉴于:
class Rocket_Engine : public Engine;
此外,此专门化可防止Rocket_Engine传递给任一函数。这些功能需要特定的引擎类型。