It is not a language flaw. C++ requires types to be complete when defining them because it needs to have access to their internal structure and layout to be in a position to apply all the optimizations that C++ is renowned for. Knowing this, at most it's a design tradeoff, and one where C++ came out winning.
For the rare cases where these irrelevant details are relevant, C++ also offers workarounds. The pimpl family of techniques is one of them, and type erasure techniques are also useful, and protocol classes with final implementations are clearly another one. Nevertheless, the fact that these techniques are far from being widely used demonstrates that there is zero need to implement them at the core language level.
And private methods aren't exactly "rare cases". The situation is bad to the point that most good codebases make less use of classes, and many average code bases avoid adding private methods and resort to code duplication to a degree.
The reason why they have to be listed anyway could be 1) a vague idea of "consistency" with e.g. public methods and generally the enforcing access control only centrally from the class declaration 2) the idea of overriding the implementation in an inherited class. As far as I'm concerned, both are bad reasons to impose such an annoying limitation to the user of the language.
Or go the same route as namespaces -- mark start and end of the class implementation code (can be repeated) and nest functions inside.
There are other options if we ditch the C/C++ compilation model. Though arguably that isn't just bad -- it's an extremely simple way to achieve separate compilation without requiring a separate (probably binary, compiler-specific) representation for compiled interfaces. The latter could probably speed up incremental builds considerably, but it's possibly slower for clean rebuilds because of dependencies.
For me, knowing that I can change the implementation details of a class and it having no possible impact on whether other code compiles or how it behaves (assuming I maintain the same "public" behaviour) is absolutely a fundamental language feature. All I'm arguing for is that compilers should be able to make the same assumption - only the private implementation details have changed, so it's unnecessary to recompile other code that happens to include the header file defining some of those implementation details.
So what is a good justification for the current language design? I did find one SO post suggesting if your suggestion were possible, the overloading rules would probably have to change, but that doesn't seem like an insurmountable hurdle.
To be clear, what you're suggesting is that header file (foo.h/hxx/hpp) would have:
class Foo {
public:
Foo();
void doYourThing();
private:
int _privInt;
std::string _privStr;
}
then foo.cxx/cpp would have something like: /*private*/ Foo::ctorHelper() {
_privInt = 42;
}
Foo::Foo() { ctorHelper(); }
/*private*/ bool Foo::anotherHelper() {
return _privStr.find("bar") != std::string::npos;
}
void Foo::doYourThing() {
if (anotherHelper()) {
std::cout << "The foo thing\n";
}
}
Whether or not some sort of keyword is needed to mark the private functions as such is stylistic I suppose - I'd prefer it were there, but I'm used to C# where the access specifier is part of every member declaration anyway. But it's certainly not necessary - the compiler would just assume "private" if the declaration is not part of the class definition.
And yes, someone else could come along and put void Foo::anotherPrivateFunction() {
}
in their own code, but they'd never be able to call it anyway, so no harm done (arguably compiler could treat an "unreferenced" private function as an error in itself, but certainly the linker would just strip it out).Obviously one downside of the above is that if you wanted friend classes to be able to call such private methods, they'd either have to forward declare them, or you'd put them into a separate "foo_private" header file, but again, I'm not seeing why that's a big problem.
Irrelevant. Private member functions aren't mandatory or required, and when developers decide to use them they explicitly state the class needs to export their symbols.
Those developers who somehow feel strongly about private member functions are a multitude of techniques to meet their needs, such as using protocol classes and move private stuff to concrete implementations, or use non-member functions either with internal linkage or stashed in anonymous namespaces.
I don't see the point of complaining that something used wrong is not being used right, while purposely ignoring the myriad of options where things are right based on your arbitrary requirements. I mean, this aspect of C++ is around for at least three decades. Don't you think that if it was a problem someone would already have noticed it?
AFAIK there isn't a nice way to deal with this other than simply not using private members and coding in a simple C like style. I don't think you've shown a way, either. I don't know what you mean by "protocol classes", but if you mean abstract classes with virtual methods that need to be overridden, those are a bad solution because they overhead of vtables without any technical need or benefits (unless you want runtime polymorphism and vtables are exactly the kind you want).
This statement is incorrect. "Definition resolution" (my made up term for FE Stuff(TM) (not what I work on)) happens during the frontend compilation phase. Optimization is a backend phase, and we don't use source level info on type layout there. The FE does all that layout work and gives the BE an IR which uses explicit offsets.
C++ doesn't allow two phase lookup (at least originally); that's why definitions must precede uses.