但是现在的问题是,我只能使用 IControllable 什么的
定义,而不是具体Controllable的具体数据和方法。
我是否应该为每个 Controllable 使用单独的容器,或者我的
在 OOP 方面逻辑是错误的?
这取决于你想对你的对象做什么。
如果您需要通过IControllable 接口大量使用所有IControllable 对象,那么将它们全部放在一个容器中是有意义的。
另一方面,如果您希望大量使用它们的特定接口,那么使用单独的容器也是有意义的。
如果你需要两者都做,那么两者都做没有错。
现在,如果您选择将所有内容放在一个容器中,那么您必须使用某种指针/智能指针,因为存储不同类型按值会导致切片并且不允许多态 em> 执行。
但是,如果可能的话,最好按值将对象存储在容器中。因此,如果您使用 多个 容器存储 按值 会更好。
如果你想两者都做,那么你可以将对象按值存储在单独的容器中,并将它们的指针存储在一个包罗万象的容器中。在这种情况下,按值存储的容器将拥有对象,因此包罗万象的容器应该不拥有它们 - 为此使用原始指针:
struct IControllable { virtual ~IControllable() {} };
struct MachineControllable: IControllable {};
struct LightControllable: IControllable {};
struct OtherControllable: IControlable {};
// store by value if possible (not always possible)
std::vector<MachineControllable> machingControlables;
std::vector<LightControllable> lightControlables;
std::vector<OtherControlable> otherControlables;
std::vector<IControlable*> allControlables; // raw pointers (non owned)
如果您不想单独存储对象,那么您的包罗万象的容器需要拥有这些对象:
// these objects die when this container dies.
std::vector<std::unique_ptr<IControlable>> allControlables;
所以真正的问题是,您将如何花费大部分时间将这些作为特定类型和/或一般(基本)类型进行处理?
还有你想要你的数据结构有多复杂?如果您使用多个容器,则会增加管理数据的复杂性。
请记住,如果您不为您的 特定 类型使用单独的容器,则必须强制转换它们以进行 特定 调用:
for(auto& controlable: allControlables)
{
MachineControllable* mc;
LightControllable* lc;
OtherControllable* oc;
if((mc = dynamic_cast<MachineControllable*>(controlable.get())))
mc->machine_specific();
else if((lc = dynamic_cast<LightControllable*>(controlable.get())))
lc->light_specific();
else if((oc = dynamic_cast<OtherControllable*>(controlable.get())))
oc->other_specific();
}
不理想。