设计问题,基类知道它的衍生物

时间:2012-04-25 07:33:08

标签: c++ base-class

基本上我有一个名为Geometry的基类,以及PointPolygon等衍生物......

Geometry实现了这样的方法交集:

Geometry* intersection(Geometry* other)
{
     Geometry* inter = compute_intersection(this, other); 

     if (inter is a polygon) 
         return new Polygon(inter);

    if (inter is a point) 
         return new Point(inter);
} 

当我计算程序中两个几何的交集时,我得到一个Geometry*,我可以dynamic_cast到它的真实状态。

这是一个好的设计吗?我认为可能是错误的是每次计算交集时都必须检查实数类型并且动态调整结果(可能很慢)。但我认为主要的问题是,使用这种设计,Geometry必须知道它的衍生物(Point,Polyline?etc ......)。

什么是避免这些问题的好方法?

5 个答案:

答案 0 :(得分:0)

为什么你需要构造一个返回对象的新对象,你能不能直接返回它?如果你不能,只需在每个衍生类中实现一个额外的方法,将compute_intersection的结果包装在一个新对象中,并在compute_intersection中调用这个新方法而不是Geometry

在我的回答中,我假设唯一可能的情况:compute_intersection是抽象的,每个派生类都实现它。

答案 1 :(得分:0)

如果你发现自己需要根据继承的类型来复制对象,那么你可以使用virtual copy constructors,通过实现一个返回对象副本的clone()函数:

virtual Obj* Obj::clone() const { return new Obj(*this); }

可以从intersection()函数调用它。

答案 2 :(得分:0)

就我而言,这里有两个问题。

首先,我并不关心获取/设置事物的功能。我更有兴趣告诉对象为我做点什么。

其次,您正在尝试实现多个调度(在本例中为双调度)。这是您需要的行为取决于多个对象的类型。

我正常的封装,封装,封装的口头禅引导我走向以下想法:

  • 封装您想要对交叉点做的事情,例如
    • 将其区域放入电子表格单元格
    • 将几何点添加到显示列表
  • 封装给定其他类型的一种类型的调度
    • 查看访客模式
  • 封装将行为应用于交叉点

答案 3 :(得分:0)

也许您可以使用boost::variant

typedef boost::variant<Point, Polygon/*, and other...*/> Geometry_Variants;

Geometry_Variants intersection(Geometry_Variants const& other)
{
    // compute the intersection and return Point or Polygon
}

答案 4 :(得分:0)

您的问题名称为multiple dispatchmulti methods。据我所知,在C ++中这个问题没有真正好的答案。 Andrei Alexandrescu对这个问题进行了很好的讨论:

http://books.google.fr/books?id=aJ1av7UFBPwC&pg=PA263&lpg=PA295&dq=modern+c%2B%2B+design+multiple+dispatch&source=bl&ots=YRdIZrWiaV&sig=2Vj0Blst_jmhMCAZIJ8gUiG_pl4&hl=fr&sa=X&ei=082XT86RHNS18QPW7f3mBQ&ved=0CCYQ6AEwAA#v=onepage&q&f=false

我建议你买这本书值得它的价值。