多态值类型和接口 [英] Polymorphic value types and interfaces
问题描述
我有一个实现如下的多态值类型:
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屋!