Markus Metz, one of the GRASS developers, described in one of his posts how such features are calculated.
Here is the quote:
For lines to lines, say line A to line B, it calculates shortest
distance of each vertex in A with each segment (not vertex) in B. So
far, this is the same like in the original version, results are
identical. Now if line A is a line or boundary, it calculates the
shortest distance of each vertex in B to each segment in A.
Additionally, it checks for intersections. In case of intersections,
the first intersection found is used and the distance set to zero.
For lines to areas, it behaves similar to the original version. If a
line is inside an area, the distance is set to zero. The first point
of the line inside the area is used as common point. The distance is
also set to zero if the line intersects with the outer ring or any of
the inner rings (isles), in which case the fist intersection is used
as common point.
For areas to areas, the module checks first for overlap or if one area
is (partially) inside the other area. This is computationally quite
intensive. If the outer rings of the two areas do not overlap, the
distance is calculated as above for lines to lines, treating the outer
rings as two lines. Again, the first point encountered falling into an
area is used as common point, or the first intersection point.
For anything else than points to lines, there can be several common
points with distance = zero, and the closest location could then be
several points or several lines or several areas (result of overlay).
For v.distance, I choose to select a single point, and not create an
overlay like v.overlay.
Hope this clears it up a little!