C ++使用彼此不相关的对象调用Double调度方法

时间:2013-01-28 04:37:08

标签: c++ double-dispatch

我有一系列形状对象可以检查它们是否相互交叉(如果任一对象的任何部分与另一个对象重叠,则交叉点为真)。这适用于双重调度,因为两个对象的交集可以相对于任一对象表示,并且仍然有效且真实。

我最近添加了(读作:“试图添加”)一个Contains方法,该方法测试一个形状是否完全包围另一个形状。双重调度失败,因为两种不同大小的形状适用于相交但不包含:shape_one是一个大圆圈,shape_two是一个完全由shape_one包围的小圆圈。调用shape_one.Contains(shape_two)将返回true,但shape_two.Contains(shape_one)将返回false。

有没有办法为这种情况实施双重调度?

(鼓励标题编辑增加对问题的理解......)

具有双重调度的Intersects方法示例:

bool Rectangle::Intersects(const Shape& shape) const {
    return shape.Intersects(*this);
}

bool Rectangle::Intersects(const Point& point) const {
    return point.Intersects(*this);
}

bool Rectangle::Intersects(const Line& line) const {
    return line.Intersects(*this);
}

bool Rectangle::Intersects(const Rectangle& rectangle) const {
    double myTop = this->GetY();
    double myLeft = this->GetX();
    double myRight = myLeft + this->GetWidth();
    double myBottom = myTop + this->GetHeight();
    double rTop = rectangle.GetY();
    double rLeft = rectangle.GetX();
    double rRight = rLeft + rectangle.GetWidth();
    double rBottom = rTop + rectangle.GetHeight();

    if(myTop > rBottom) return false;
    if(myBottom < rTop) return false;
    if(myLeft > rRight) return false;
    if(myRight < rLeft) return false;

    return true;
}

包含双重调度的方法的示例:

//THIS RESULTS IN A STACK OVERFLOW! DUE TO INFINITE RECURSION!
bool Rectangle::Contains(const Shape& shape) const {
    return this->Contains(shape);
}

//THIS IS NOT TRUE IN ALL CASES!
bool Rectangle::Contains(const Shape& shape) const {
    return shape.Contains(*this);
}


bool Rectangle::Contains(const Point& point) const {
    return this->Intersects(point);
}

bool Rectangle::Contains(const Line& line) const {
    return this->Intersects(line.GetPointOne()) && this->Intersects(line.GetPointTwo());
}

bool Rectangle::Contains(const Rectangle& rectangle) const {
    return this->Intersects(rectangle.GetTopLeft()) && this->Intersects(rectangle.GetTopRight()) && this->Intersects(rectangle.GetBottomLeft()) && this->Intersects(rectangle.GetBottomRight());
}

1 个答案:

答案 0 :(得分:0)

解决方法通过推送包含方法直到基类和动态强制转换为正确的类型,并在base-to-base包含调用中使用类型参数:

bool Shape::Contains(const Shape& shape) const {
    std::string type = shape.GetShapeType();
    if(type == "arc") {
        return this->Contains(dynamic_cast<const Arc&>(shape));
    } else if(type == "circle") {
        return this->Contains(dynamic_cast<const Circle&>(shape));
    } else if(type == "ellipse") {
        return this->Contains(dynamic_cast<const Ellipse&>(shape));
    } else if(type == "line") {
        return this->Contains(dynamic_cast<const Line&>(shape));
    } else if(type == "point") {
        return this->Contains(dynamic_cast<const Point&>(shape));
    } else if(type == "polygon") {
        return this->Contains(dynamic_cast<const Polygon&>(shape));
    } else if(type == "rectangle") {
        return this->Contains(dynamic_cast<const Rectangle&>(shape));
    } else if(type == "sector") {
        return this->Contains(dynamic_cast<const Sector&>(shape));
    } else if(type == "spline") {
        return this->Contains(dynamic_cast<const Spline&>(shape));
    } else if(type == "triangle") {
        return this->Contains(dynamic_cast<const Triangle&>(shape));
    } else {
        return false;
    }
}

bool Shape::Contains(const Point& point) const {
    return this->Intersects(point);
}

bool Shape::Contains(const Line& line) const {
    return this->Intersects(line.GetPointOne()) && this->Intersects(line.GetPointTwo());
}

bool Shape::Contains(const Rectangle& rectangle) const {
    return this->Intersects(rectangle.GetTopLeft()) && this->Intersects(rectangle.GetTopRight()) && this->Intersects(rectangle.GetBottomLeft()) && this->Intersects(rectangle.GetBottomRight());
}

//...etc