Martin's comment is on the right lines. The
--cycle syntax draws a straight line from the current point on the path to the start of the last component. A component means a continuous path, so is marked by the last
moveto. The actual implementation of this is handled either by the driver or the renderer so TikZ doesn't control how the corners are handled in this situation.
The problem with what you are trying to do is that your path is interrupted by moves. The symbols are placed by using nodes and the path has to be broken in order to go around them. This is made clear if we examine the path that is actually defined. If we take your middle example and look at the actual path, we get:
So we start with a
moveto (every path starts with a
moveto) then draw a line straight up. This is followed by another
moveto: that's the move that skips the voltage source. Then we get a
lineto up to the corner. (In fact, we get two
linetos, but the second is effectively a NOP. Presumably there's some complicated case where it would come into play.) Our next journey is across the top and then we start the descent. Again, we break our journey to make space for the resistor and then finish the downward part in the corner (again with a double
lineto). The last stage is the
closepath which closes up the path (must've been a genius who came up with that name). The coordinates of the
closepath aren't actually used, but can indicate (to the user) where the closing line should go. In this case, it goes to the bottom of the resistor. As this line is already drawn, we don't notice this.
Drawing just the path produces the red line in the following:
Of course, we can't see the
closepath here because it is on top of the path already drawn. If we take out the resistor, then we can see this
closepath in action:
It may be hard to see, but the closed path is genuinely closed.
The difficulty here is that
--cycle always produces a closed path. But that's not what you want. What you want is to join the end back to the start. Exactly how to do this depends on how automatic and how faithful you want the solution to be. "Automatic" is fairly obvious, "faithful" is perhaps less so. What I mean by that is whether you want the paths to be actually joined, or whether the simulation is enough.
If simulation is enough, and all your corners are at right angles, then a simple
line cap=rect ought to suffice. This ensures that line ends protrude by half the line width. Compare:
Unfortunately, on my test run (with your code), the infinitesimal lines interfere with this and I don't get a clean corner in the lower right. (However, I don't get a clean corner there with your code either so I suspect that we have different PGF versions and that this might be an okay solution for you ... Hang on: having now uploaded the picture I see that the fact that I don't see a clean corner in the lower right is due to my PDF viewer!)
Incidentally, note that this also fixes the small white lines in your picture between the "wires" and the "symbols". Normally these wouldn't be visible anyway - they are there because of the extra thick lines and the inaccuracy of placing lines at exactly the right place.
To do this automatically and faithfully what we would have to do is take the path and process it a little. We'd have to take the initial component (being the little upward stretch) and join it to the last component, so that the path now began with the bit emanating out of the resistor. This is perfectly possible with low-level code and I have all the pieces in my
spath library, they just need to be put together in a sensible way.