c++ - 解决这个多态性问题的最优雅的方法

标签 c++ polymorphism

编辑:我正在使用 C++。

因此,我正在创建方法/函数来测试形状之间的交集。我基本上有这个:

class Shape {};

class Rectangle : public Shape {};

class Circle : public Shape {};

class Line : public Shape {};

现在,我需要决定编写实际方法/函数来测试交集的最佳方式。但是我所有的形状都将存储在一个形状指针列表中,所以我将调用基本形式的方法/函数:

bool intersects (Shape* a, Shape* b);

此时,我需要确定形状“a”和“b”的类型,以便正确检测碰撞。我可以轻松地完成其中之一,只需使用一些虚拟方法:

class Shape
{
    virtual bool intersects (Shape* b) = 0;
}

这将确定其中一个形状(“a”现在是“this”)。但是,我仍然需要获得“b”的类型。显而易见的解决方案是给 Shape 一个 'id' 变量来分类它是哪种形状,然后通过这些变量进行“切换”,然后使用 dynamic_cast。然而,这不是很优雅,感觉应该有一种更面向对象的方式来做到这一点。

有什么建议吗?

最佳答案

正如@Mandarse 所指出的,这是典型的双重分派(dispatch)问题。在面向对象的语言中,或者像可以实现面向对象概念的 C++ 语言中,这通常使用 Visitor 来解决。图案。

通常,Visitor 接口(interface)本身为每个具体类型定义一个回调。

class Circle;
class Rectangle;
class Square;

class Visitor {
public:
  virtual void visit(Circle const& c) = 0;
  virtual void visit(Rectangle const& r) = 0;
  virtual void visit(Square const& s) = 0;
};

然后,Shape 层次结构为此进行了调整。我们需要两种方法:一种接受任何类型的访问者,另一种创建“适当的”路口访问者。

class Visitor;
class Intersecter;

class Shape {
public:
  virtual void accept(Visitor&) const = 0; // generic
  virtual Intersecter* intersecter() const = 0;
};

相交很简单:

#include "project/Visitor.hpp"

class Intersecter: public Visitor {
public:
  Intersecter(): result(false) {}
  bool result;
};

例如,对于 Circle 它将给出:

#include "project/Intersecter.hpp"
#include "project/Shape.hpp"

class Circle;

class CircleIntersecter: public Intersecter {
public:
  explicit CircleIntersecter(Circle const& c): _left(c) {}

  virtual void visit(Circle const& c);    // left is Circle, right is Circle
  virtual void visit(Rectangle const& r); // left is Circle, right is Rectangle
  virtual void visit(Square const& s);    // left is Circle, right is Square

private:
  Circle const& _left;
}; // class CircleIntersecter


class Circle: public Shape {
public:
  virtual void accept(Visitor& v) const { v.visit(*this); }

  virtual CircleIntersecter* intersecter() const {
    return new CircleIntersecter(*this);
  }
};

以及用法:

#include "project/Intersecter.hpp"
#include "project/Shape.hpp"

bool intersects(Shape const& left, Shape const& right) {
  boost::scope_ptr<Intersecter> intersecter(left.intersecter());
  right.accept(*intersecter);
  return intersecter->result;
};

如果其他方法需要双分派(dispatch)机制,那么您需要做的就是创建另一个“Intersecter-like”类来包装结果并继承自 Visitor 和一个新的“Factory”方法 Root 于 Shape,它被派生类覆盖以提供适当的操作。它有点冗长,但确实有效。

注意:除了 intersect(circle, rectangle)intersect(rectangle, circle) 之外,产生相同的结果是合理的。您可以将代码分解为一些方法,并将 CircleIntersecter::visit 委托(delegate)给具体实现。这避免了代码重复。

关于c++ - 解决这个多态性问题的最优雅的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9014471/

相关文章:

java - 多态类/多态性/内部类-获取错误信息

c++ - 如何将#ifndef 与宏参数一起使用?

c# - 过时的意思

c++ - 使用快速傅里叶变换模糊矩阵

C++:调用 OBJ、OBJ&、const OBJ& 时实现不同的方法

c++ - 检查 bool 是否比调用空函数更有效?

java - 堆栈溢出二叉搜索树计算深度

c++ - 处理模板创建的更好方法?

c++ - 条件运算符的返回值

c++ - 在双重继承的情况下如何处理非标准构造函数