This sounds tailor-made for a double-dispatch solution. Perhaps not
precisely the visitor pattern, but similar.
First, you'll want to re-order your overloads so that the base class overload comes last. I don't know if that will make a difference, but I think it might. You want the others to be preferred when possible.
Second, define the base class version like so:
Code:
bool CollideBox::collide(Collision* other)
{
other->collide(this);
}
Now, it make take two collide() calls to fully resolve what's going on, but you can be sure that each call will resolve exactly one base class pointer into its concrete type via the virtual function table.
Unfortunately, even though each class derived from Collision must have the same implementation (above) in the generic case, I think you can't just write it once in the base class in this case. We're relying here on "this" being passed as the derived type, after all.