Earlier quoted context omitted.
The best guard against unintended uses that hamstring the maintenance of the library is the good old opaque handle: typedef struct foo_struct *foo; foo foo_make(); void foo_destroy(foo); void foo_frobnicate(foo, int how); The client executables have no idea how big a foo object is, or what alignment requirements are, let alone what its members might be. The client executables don't control the allocation, constructio…
That doesn't solve the problem the OP solves, which is to expose a method only to a specified set of other classes.
I think you could also solve this specific problem with an internal header file in c++ too (by moving register/deregister to it's own class) but this solution solves other problems like binary compatibility.