C++中的动态特设多态性



在我的C++代码中,我有一组类A1, A2, ...,,它们都是从一个类A派生的。我还有一个向量v<*A>,它包含指向所有类型为A的对象的指针。我想实现一个函数foo(A *x, A *y),它是xy类型的动态自组织多态函数。更具体地说,假设AShapeA1, A2, ...,Circle, Rect, ...,foointersects(Shape *x, Shape *y)

对于我关心的A的派生类型的组合,我可以用foo(A1 *x, A2 *y)之类的声明重载foo,但这对我的向量v引用的对象不起作用,因为函数重载与虚拟方法不同,是静态处理的。我也不能使用形式为A1::foo(A2 *y)的虚拟方法,因为这只动态解析方法类(A1(的类型,而不是参数(A2(的类型。

我想到的唯一解决方案是实现foo,如下所示:

void foo(A *x, A*y) {
if (A1* a1 = dynamic_cast<A1*>(x)) {
if (A1* a1 = dynamic_cast<A1*>(y)) {
...
}
...
}
if (A2* a2 = dynamic_cast<A2*>(x)) {
if (A1* a1 = dynamic_cast<A1*>(y)) {
...
}  
...
}
...
}

然而,我一直被告知,采用动态演员阵容很少是个好主意。有没有更惯用的方法来实现这一点?

这是双重调度。访问者模式可以实现这一点。您需要一个虚拟函数,使第一种类型具体化以应用访问者。然后你需要另一个虚拟函数来使第二种类型具体化并返回访问者:

struct Shape
{
// Each derived class simply calls visit with the concrete type:
//     return visitor.visit(*this);
virtual bool accept(const IntersectionVisitor& visitor) const = 0;
// Each derived class return a visitor which knows how to calculate
// the intersection of this particular class type with all types of
// shapes. The visit() overrides of this visitor have access to both
// concrete shape types.
virtual IntersectionVisitor intersection_visitor() const = 0;
};
struct IntersectionVisitor
{
// Calculate the intersection of this concrete shape with a Circle
virtual bool visit(const Circle&) = 0;
// Calculate the intersection of this concrete shape with a Rect
virtual bool visit(const Rect&) = 0;
};
bool intersects(const Shape& shape1, const Shape& shape2)
{
return shape2.accept(shape1.intersection_visitor());
}

仅仅因为你可以并不意味着你应该。你可以用变体更简单地做到这一点:

using Shape = std::variant<Circle, Rect, ...>;
bool intersects(const Circle&, const Circle&) { ... }
bool intersects(const Circle&, const Rect&) { ... }
// all shape combinations, like before
// Visitation is just std::visit:
bool intersects(const Shape& shape1, const Shape& shape2)
{
return std::visit([](const auto& s1, const auto& s2) {
return intersects(s1, s2);
}, shape1, shape2);
}

最新更新