It is not trivial task. Generally said, you can't simply use dlsym
here. Unlike C, C++ mangles symbol names, mangling standards may vary from implementation to implementation and even from version to version of the same compiler. You still can use functions, exported in accordance with C conventions, but I'm afraid, using whole types (C++ classes) would be impossible without headers.
Lazy loading and using shared objects exporting classes always been rather tricky in C++. You can use special functions like in this tutorial, or you can use more advanced techniques like factories, finally, you can rely on your complier/linker (all popular modern compilers support this), but either way you need some info about types you're going to use in your program and this info should be available at compile time. This information contained in header files. So, the answer to your question is rather negative.
On name mangling and why it's "evil" see links in comments. (Don't take this too literally - there are technical reasons for this, even while this feature makes life harder sometimes :-))