I like Boost's approach[1] of using a separate namespace for these implementation-specific things, rather than visibility modifiers.
Then the internals are accessible if you need it for a temporary workaround or such, but it's also very obvious when you are accessing stuff you really shouldn't. And implementers are still free to rearrange the internals as they see fit.
[1]: Not saying Boost invented it, just where I saw it first.
Boost uses both. Implementation-private namespaces are a slightly different feature. They provide a way to share internal methods between classes within boost that must not be used by client code. That's a scoping feature that c++ doesn't have, but c# (for example) does.
Then the internals are accessible if you need it for a temporary workaround or such, but it's also very obvious when you are accessing stuff you really shouldn't. And implementers are still free to rearrange the internals as they see fit.
[1]: Not saying Boost invented it, just where I saw it first.