C++ is worse than most languages in this way, because private members are defined in public headers. This forces you add #includes to the headers. Thus the #include graph is much denser than the true dependencies in your program.
There's tricks for getting around this, but they aren't always practical; and they go against the grain of the "every class has its own .cpp and .h file" rule, which lots of people want to insist on.
You mean PIMPL?
I am referring to writing a base class in the header and then doing the actual implementation in a derived class visible only inside one .cpp file. There are some other tricks you can do too, such as using pointers-to-incomplete types.
When I do any of these tricks, find that someone else later comes and makes a changes that introduces the extra #includes after all.
>every class has its own .cpp and .h file
Wrong. There are so many high-quality and widely-used libraries that are "header only".
>When I do any of these tricks, find that someone else later comes and makes a changes that introduces the extra #includes after all.
It is possible to write sloppy code in any language, and also to receive low-quality contributions from anyone else to your code. This is not unique to C++. That's why it is important that everyone in a team be on the same page about how code is organized.
>I am referring to writing a base class in the header and then doing the actual implementation in a derived class visible only inside one .cpp file.
This is not the PIMPL idiom, though it is halfway right.
For objects that are used in setting up parts of a system and that will persist for long periods of time, maybe even the lifetime of the app, PIMPL is particularly well-suited for such classes. Classes that might manage networking, or encompass an entire part of app's running architecture, etc.