Using hidden visibility is a great way to ensure your library is only being used through specified access points. This is a huge advantage if you ever modify it, as you know exactly how your library is being used externally and therefore the limitation of what you might potentially break.
It is a very similar technique to Windows making you declspec what is part of the accessible part of a DLL, except the slight difference that you do not state if you are importing or exporting, and your library may therefore be making "visible" functions it uses rather than implements.
To answer your question though, I think visibility is only supported version 4 onward. Certainly we use it here with this
#if defined(__GNUC__) && __GNUC__ >= 4
When you use hidden visibility, you need to explicity state which symbols you do wish to be visible. Thus you have this:
__attribute__((visibility("default")))
which you will probably #define to be something more readable, maybe SO_EXPORT thus:
#define SO_EXPORT __attribute__((visibility("default")))
The define classes:
class SO_EXPORT MyAccessInterface;
and methods something like:
SO_EXPORT int doSomething( parameters );
We actually also have a similar macros for hidden visibility (as above but with "hidden" instead of "default"). Thus even when we use "default" visibility for the whole project we can hide some implementation detail.
#define SO_HIDDEN __attribute__((visibility("hidden")))
class SO_HIDDEN MyClassImpl;