I tried to reply to the comments above, but unfortunately I currently lack the reputation to do so. I'll answer here and moderators can feel free to recategorize as appropriate.
We do exactly this...we have a shared base package with common SObjects, Apex classes, Visualforce pages, remote site settings (all of our apps are hybrids and make callouts to the back end), permission sets, etc., and we have multiple extension packages that represent the actual applications. The SObjects in the base package generally represent shared configuration objects for our applications as well as the UIs for those objects in the form of Visualforce pages and Apex controller classes. The base package also contains a number of common Apex utility classes and the declarative authorization model in the form of packaged permission sets.
There are definitely pros and cons to this even ignoring the additional security review overhead. On the positive side, for the most part we do get the desired code and data reuse. I qualify "for the most part" because some limitations and even bugs in the Salesforce packaging model keep us from taking full advantage of this like we would in a language with a more well-defined, granular packaging model. There are workarounds for most of these, though some do require limited clone-and-own or even additional onerous steps at packaging time.
On the negative side, development of multiple managed packages with base/dependency relationships can be a serious pain! The most obvious approach is to do this in multiple dev orgs, one-per managed package, and go through a constant cycle of deploying, uploading, uninstalling, installing, and deploying. By the way, when I say "multiple dev orgs", I mean multiple per-individual contributor plus multiple for testing and of course for releasing. With this approach, cycle times can be very long to test a change that crosses both packages. We've since figured out how to develop content for multiple packages in a single dev org. This definitely helps with the development process, but it comes with its own issues since it doesn't model the real production deployment topology. If you'd like more information, I spoke about this in detail at Dreamforce 2014:
I agree with the poster above that if it's almost exclusively code that you're needing to share, having a common repository for that in source code management that is mapped into each package at build/packaging time is an option that you should consider. If, on the other hand, like us you really need to share persisted state between applications and that persisted state must live in Salesforce, you probably need multiple managed packages with base/extension relationships like this. I guess a third option might be more along the lines of a microservices approach where you have peer packages (vs. base/extension) which communicate with one another via SSO, though you're going to need to work through the security implications of that very carefully. Also, this would almost certainly need to be more coarse-grained than any real microservices approach to avoid an unmanageable explosion in the number of managed packages.
I'm happy to share more about our experience with this if you're interested. Just let me know...