I’m an old (but not too old) Java programmer, that decided to learn C++. But I have seen that much of C++ programming style, is… well, just damn ugly!
All that stuff of putting the class definition in a header file, and the methods in a different source file- Calling functions out of nowhere, instead of using methods inside classes. All that just seems… wrong!
So finally, is there any reason for me to continue with this massacre to the OOP, and anything that is good and righteous in programming, or can I just ignore that old-fashioned C++ conventions, and use my good Java programing style?
By the way I’m learning C++, because I want to do game programing.
Here is an example:
In an C++ website I found a Windows implementation:
class WinClass { public: WinClass (WNDPROC wndProc, char const * className, HINSTANCE hInst); void Register () { ::RegisterClass (&_class); } private: WNDCLASS _class; };
That class is located in a header file and the constructor:
WinClass::WinClass (WNDPROC wndProc, char const * className, HINSTANCE hInst) { _class.style = 0; _class.lpfnWndProc = wndProc; // Window Procedure: mandatory _class.cbClsExtra = 0; _class.cbWndExtra = 0; _class.hInstance = hInst; // Owner of the class: mandatory _class.hIcon = 0; _class.hCursor = ::LoadCursor (0, IDC_ARROW); // Optional _class.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1); // Optional _class.lpszMenuName = 0; _class.lpszClassName = className; // Mandatory }
Is located at a .cpp source file.
What I could just do is:
class WinClass { public: WinClass (WNDPROC wndProc, char const * className, HINSTANCE hInst) { _class.style = 0; _class.lpfnWndProc = wndProc; // Window Procedure: mandatory _class.cbClsExtra = 0; _class.cbWndExtra = 0; _class.hInstance = hInst; // Owner of the class: mandatory _class.hIcon = 0; _class.hCursor = ::LoadCursor (0, IDC_ARROW); // Optional _class.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1); // Optional _class.lpszMenuName = 0; _class.lpszClassName = className; // Mandatory } void Register () { ::RegisterClass (&_class); } private: WNDCLASS _class; };
And now the constructor is inside its class.
In addition to what others have said here, there are even more important problems:
1) Large translation units lead to longer compile times and larger object file sizes.
2) Circular dependencies! And this is the big one. And it can almost always be fixed by splitting up headers and source:
No matter what order you put these in, one will always be lacking the definition of the other, even using forward declarations it won’t work, since in the function bodies are using specifics about each class’s symbol.
But if you split them up into proper .h and .cpp files and use forward declarations it will satisfy the compiler:
Now the code that actually has to know specifics about the second class can just include the header file which doesn’t need to know specifics about the first class.
Headers just provide the declarations while source files provide the definitions. Or another way to say it: Headers tell you what is there (what symbols are valid to use) and source tells the compiler what the symbols actually do. In C++ you don’t need anything more than a valid symbol to begin using whatever it is.
Trust that C++ has a reason for this idiom, because if you don’t you will make a lot of headaches for yourself down the line. I know :/