c ++设计:继承和返回不透明句柄

时间:2015-10-02 23:38:35

标签: c++ inheritance type-safety

我有两个接口,如下所示:

class IThing {
    ...
    virtual IHandle* getHandle(void) = 0;
    virtual void useHandle(IHandle *handle) = 0;
};

class IHandle { ... }

我希望用户能够实现IThing和IHandle。例如,如果用户创建MyThingMyHandle,则getHandle应返回指向MyHandle的指针,用户稍后可在useHandle中使用该指针。 / p>

这样可行,但我不喜欢这种设计,因为IHandle的多个实现可能会在IThing的实现之间混淆。同样在useHandle中,用户需要明确地向下转换为IHandle的实现。是否有更安全的方式来做到这一点?

1 个答案:

答案 0 :(得分:0)

我不太确定你想要设计什么。但在这里,我希望有些想法可能会有所帮助。

基本原则是公开派生自IThing的类确实是IThing。您可以使用IThing执行此操作,您可以使用MyThing,包括获取IHandle

只要您的IHandle衍生品都遵循相同的原则,就没有设计问题。这意味着您的东西不应该对特定句柄做出任何假设,反之亦然。

如果您使用MyHandle假设与MyThing相关联(或反之亦然),那么您将会遇到您描述的问题。实际上,您使用的是在类定义中未表达的依赖项。所以,是的,你将不得不使用垂头丧气。这是不可能的,因为它揭示了一个设计问题。

由于您的类是多态的,您可以通过使用dynamic_cast检查nullptr来限制向下转换风险。但这是一种解决方法,而不是设计改进。

或者你可以考虑模板。它们可以帮助您在编译时链接相关类型。您将获得类型安全性,但是您将失去运行时多态性的一些灵活性。一个示例方法:

template <class IH>
class IThing  {   
public:
    virtual IH* getHandle(void) =0;
    virtual void useHandle(IH *handle) =0;
};

class MyHandle {  };  // to keep it simple, 

class MyThing: public IThing<MyHandle> {}; // instantiation with specific handle

int main() {
    MyThing i; 
    MyHandle *h;
    h = i.getHandle(); 
    ...
 }

此示例中的约束是,您不要使用不同的句柄混合不同的IThings