OOP has composition and substitution.
C++ has multiple inheritance, template specialisation, embedding and value/move/pointer semantics.
Java has single inheritance and interfaces, embedding and reference semantics.
The common way the OOP school uses these languages is to employ inheritance for object substitution and embedding for composition. But you also need a common ancestor and a way to runtime-cast (in C++ is called dynamic_cast
, in Java is just asking an interface from another).
Java does all this by its own java.lang.Object
rooted hierachy. C++ doesn't have a predefined common root, so you should at least define it, to come to a same "picture" (but this is limiting some C++ possibilities...).
After that, the possibility to have compile-time polymorphism (think to CRTP) and value semantic can offer also other alternatives to the way the concept of "OOP object" can be ported into a C++ program.
You can even imagine the heresy to use embedding and implicit conversion to manage substitution and private inheritance to manage composition, in fact inverting the traditional school paradigm. (Of course, this way is 20 years younger than the other, so don't expect a wide community support in doing that)
Or you can imagine a virtual common base to all classes, form interface (no implementation) to final classes (fully implemented) going through partially implemented interfaces an even interface clusters, using "dominance" as dispatching from interface to implementations through a "multi stacked-parallelogram" inheritance scheme.
Comparing OOP to java to C++ assuming there is just one and only OOP way is limiting the capabilities of both the languages.
Forcing C++ to strictly adhere to Java coding idioms is denaturating C++ as forcing Java to behave as a C++-like language is denaturating Java.
Is not a matter of "sensibility" but of different "aggregation mechanisms" the two languages have and different way to combine them that makes some idiom more profitable in one language than the other and vice versa.
Best Answer
I would put it (like any other class) in the package it belongs most from it's content. That mostly - but not everytime - means, that you put it in the same package as implementing classes. Sometimes you put an abstract class in the same package as some other class using this abstract class - it's part of the API of the other class. Implementing classes could be somewhere else in that case. I never use extra packages for abstract classes or other stuff like exception-classes or so.
Why so? I prefer to use package-structure as building a system for categorizing the content of the software, instead as using it for implementation details. The abstract-class may become later a valid non-abstract-class without breaking the API. But if I have to move it's package it would break again old code. Unnessecary I think.