Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Your second edit indicates that the basic intersection routine will operate using some <code>furthest_along</code> code. You could make use of that, in such a way that normal intersection checks operate on a common base class which includes this <code>furthest_along</code> in its interface. You would need special functions only for special cases, for which you want other algorithms.</p> <p>The following example avoids all dynamic casts and performs two virtual method invocations instead (also known as “<a href="http://en.wikipedia.org/wiki/Double_dispatch#Double_dispatch_in_C.2B.2B" rel="nofollow">double dispatch</a>”, which by the way is also available as a <a href="/questions/tagged/double-dispatch" class="post-tag" title="show questions tagged 'double-dispatch'" rel="tag">double-dispatch</a> tag, so adding that to your question might be useful).</p> <pre><code>struct Geometry { virtual ~Geometry() { } virtual Point furthest_along(Vector&amp; v) const = 0; virtual bool intersects(const Geometry&amp; other) const { return other.intersects_impl(*this); } virtual bool intersects_impl(const Geometry&amp; other) const { // default impl // compute intersection using furthest_along } virtual bool intersects_impl(const Circle&amp; other) const { return intersects_impl(static_cast&lt;const Geometry&amp;&gt;(other)); // use default } }; struct Circle : public Geometry { bool intersects(const Geometry&amp; other) const { return other.intersects_impl(*this); // call intersects_impl(const Circle&amp;) } bool intersects_impl(const Circle&amp; other) const { // do circle-circle intersection } Point furthest_along(Vector&amp; v) const { // implement for default intersection } }; struct Rectangle : public Geometry { Point furthest_along(Vector&amp; v) const { // implement for default intersection } }; </code></pre> <p>If you call <code>a.intersects(b)</code>, then the <code>intersects</code> method will be chosen from the virtual function table of <code>a</code>, whereas the <code>intersects_impl</code> method will be chosen from <code>b</code>. If you want to add a special case for the type combination <code>A</code> and <code>B</code>, you'll have to add</p> <ol> <li>a virtual method <code>Geometry::intersects_impl(const A&amp;)</code>, delegating to the default</li> <li>an override method <code>A::intersects</code> delegating to <code>intersects_impl(const A&amp;)</code></li> <li>an override method <code>B::intersects_impl(const A&amp;)</code> with the actual custom code</li> </ol> <p>If you have to add many types with many special case algorithms, this might amount to a fairly high number of modifications in various places. If, however, most shapes that you add will be using the default implementation, then all you have to do is properly implementing <code>furthest_along</code> for each of these.</p> <p>You can of course do more clever things than this. You can create an intermediate class <code>ConvexGeometry</code> which uses the <code>furthest_along</code> approach, and a class <code>NonConvexGeometry</code> which would provide some means for partitioning into convex pieces. You could implement <code>intersects</code> in both of these and make the implementation in <code>Geometry</code> purely abstract (<code>= 0</code>). You could then avoid <code>intersects_impl(const Geometry&amp;)</code> and instead use <code>intersects_impl(const ConvexGeometry&amp;)</code> and <code>intersects_impl(const NonConvexGeometry&amp;)</code> as the default mechanisms, both of which could be <code>= 0</code> in <code>Geometry</code> and implemented appropriately in <code>ConvexGeometry</code> and <code>NonConvexGeometry</code>. But if you understand the idea behind the above code, then adding these extensions should be simple enough. If not, ask.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload