多态值类型和接口 [英] Polymorphic value types and interfaces

查看:50
本文介绍了多态值类型和接口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个实现如下的多态值类型:

I have a polymorphic value type implemented like so:

class ShapeValue {
  public:
    template<class T>
    ShapeValue(const T& value) {
       obj = make_unique<holder<T>>(value);
    }
    // ... appropriate copy constructors and such

    void draw() { obj->draw(); }

  private:

    struct base {
       virtual ~base() {}
       virtual void draw() = 0;
    };

    template<class T>
    struct holder<T> : public base {
       T value;
       void draw() override { value.draw(); }
    }

    unique_ptr<base> obj;
};

如果您不熟悉这种事情,请这里是个好话.

If you aren't familiar with this sort of thing, here's a good talk.

好的,太好了.但是现在,如果我想将基础对象强制转换为其他接口怎么办?

Ok, that's great. But now what if I want to cast my underlying object to some other interface?

这是我的动力.以前,我以典型方式定义事物,例如:

Here's my motivation. Previously, I had defined things the typical way, like so:

class Shape {
   virtual void draw() = 0;
};

然后我将定义其他接口,例如:

and then I would define other interfaces, like:

class HasColor {
   virtual Color color() = 0;
   virtual void setColor(Color) = 0;
};

所以我可以定义如下形状:

so I could define a shape as follows:

class MyShape : public Shape, public HasColor {
   void draw() override;
   Color color() override;
   void setColor(Color) override;
};

因此,如果我有一堆选定的形状并且想要设置它们的颜色,则可以遍历所有形状和 dynamic_cast< HasColor *> .事实证明,这非常方便(顺便说一句,我的实际应用程序不是绘图应用程序,但是具有类似的数据).

So if I have a bunch of selected shapes and I want to set their color, I could iterate over all shapes and dynamic_cast<HasColor*>. This proves to be quite convenient (my actual app isn't a drawing app, by the way, but has analogous data).

我可以针对我的多态值类型执行此操作吗,而我的 ShapeValue 接口不需要了解每个 Has 接口?我可以执行以下操作,虽然实际上还不错,但并不理想:

Can I do this for my polymorphic value type, in a way that my ShapeValue interface doesn't need to know about every Has interface? I could do the following, which isn't actually so bad, but not ideal:

HasColor* ShapeValue::toHasColor() { return obj->toHasColor(); }

推荐答案

一种解决方案(经过测试)将具有用于接口的基类:

A solution (tested) is to have a base class for the interfaces:

class AnyInterface {
   virtual ~AnyInterface() {} // make it polymorphic
};

struct HasColor : public AnyInterface {
   // ... same stuff
};

所以我们有以下内容:

vector<AnyInterface*> ShapeValue::getInterfaces() { return _obj->getInterfaces(); }

然后可以定义一个助手来获取我们想要的界面:

Could then define a helper to grab the interface we want:

template<class I>
I* hasInterface(Shape& shape) {
   for(auto interface : shape.getInterfaces()) {
       if(auto p = dynamic_cast<I*>(interface)) {
           return p;
       }
   }
   return nullptr;
}

通过这种方式, ShapeValue 不需要了解所有接口类型.

This way ShapeValue does not need to know about all the interface types.

这篇关于多态值类型和接口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆