C ++继承,接口

时间:2015-06-07 16:26:37

标签: c++ inheritance interface

假设我有一个接口IControllable,3个类继承了该接口:MachineControllable, LightControllable, OtherControllable,它有一些特定的数据和方法。

现在我确实只想拥有一个所有IControllable的容器,所以我创建了一个矢量容器。

vector<IControllable> allControllables; // and put all the MachineControllable,
//LightControllable, OtherControllable here by the IControllable interface class.

但现在的问题是,我只能使用IControllable定义的内容,而不是特定Controllable的具体数据和方法。

我应该为每个Controlable分配容器,还是我的逻辑在OOP方面是错误的?

4 个答案:

答案 0 :(得分:4)

  

“我应该为每个Controlable分配容器,还是我的逻辑在OOP方面是错误的?”

不,你的逻辑没问题。问题是,你不能实例化一个抽象类。

你应该有一个容器保持指向IControllable接口的指针,例如:

 vector<IControllable*> allControllables;

 vector<std::unique_ptr<IControllable>> allControllables;

 vector<std::shared_ptr<IControllable>> allControllables;

答案 1 :(得分:2)

如上所述,你的向量应该包含某种指针,而不是基础对象本身。

一旦有了这个,你需要一种方法来获取容器中实际对象类型的特定指针。标准方法是使用dynamic_cast

IMachineControllable * p = dynamic_cast<IMachineControllable*>(allControllables[i]);

如果选择了错误的类型,则会得到一个NULL指针。

如果这些是Microsoft COM接口,则需要使用替代方法,但除非您说明您的所有内容,否则我不会参与其中。

答案 2 :(得分:1)

这可能不是唯一的问题。容器需要价值 语义,并包含您放入的对象的副本 他们。继承通常不适用于copy和 任务:想想如果你有什么可能意味着什么:

*p = *q;

其中pqIControllable*,但p指向 MachineControllabe,但是qLightControllable。作为一个 一般规则(并且例外),你应该做 接口不可操作且不可分配。通常,他们也是 还将包含纯虚函数,这意味着你 无法实例化它们。在任一情况下, std::vector<IControllable>甚至不会编译。

您可能想要的是std::vector<IControllable*>。 无论如何,多态性只能通过指针或引用来工作 (你不能有参考文献)。

答案 3 :(得分:1)

  

但现在的问题是,我只能使用IControllable   定义,而不是特定Controllable的具体数据和方法。

     

我应该为每个可控制器分配容器,还是我的   逻辑在OOP方面是错误的吗?

这取决于您对对象的要求。

如果您需要通过IControllable界面使用 heavy 使用所有IControllable个对象,那么将它们全部放在一个容器中是有意义的。

另一方面,如果您想使用特定的接口,那么拥有单独的容器也是有道理的。

如果你需要同时做到这两点,那么两者都没有错。

现在,如果您选择将所有内容放在一个容器中,那么您必须使用某种指针/智能指针,因为按值存储不同类型将导致切片并且不允许多态 em>执行。

但是,如果可能,最好通过 value 将对象存储在容器中。因此,如果您使用多个容器,则按存储将更为可取。

如果要同时执行这两项操作,则可以按值将对象存储在单独的容器中,并将其指针存储在catch-all容器中。在这种情况下,按值存储的容器将拥有对象,因此catch-all容器应拥有它们 - 使用原始指针:

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)

如果您不想单独存储对象,那么您的catch-all容器需要拥有对象:

// 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();
}

不理想。