Archived

This topic is now archived and is closed to further replies.

Rellik

Rationale for Avoiding Implementation in C++ Headers?

Recommended Posts

Over time, I have gotten the sense that it is considered bad form to include the implementation of a function or class or structure or anything inside the header file itself. It seems to me that including the implementations, especially if they are basic and vital calculations of some sort, or some messy file-format or OS stuff that you want easy access to, helps keep your code nicely packaged and distributed. What is the purpose of declaring everything in a header and then implementing everything in a source file? Any tips for distributing code? On a related note, what exactly is "inline"? This means that instead of calling a function, the code of the function is just copied to wherever was calling the function, correct? I''m assuming that the advantage is in speed, eliminating function-call overhead, and the disadvantage is in overall code and thus executable size, but that''s just a guess. I feel like I may have actually looked into this at some point, and am just forgetting; but my question is, what exactly is the practical application of the "inline" (and for that matter, the "extern") keyword? Isn''t it similar to a macro (assuming I was on the right track)? I hate to make a habit of these "multi-threads", but I have one more question for now. It''s just a basic question, verifying what I know about headers and source. Headers are concatenated to the beginning of the source they are included in prior to compile. When a function is called that has no implementation, it searches for the implementation. Here is my main question: where does it search? The source file of the same name? The entire body of files specified as being members of the project? Thanks.

Share this post


Link to post
Share on other sites
You are correct about inlining.

As for keeping implimentation out of the header, aside from making cleaner code (you can look at prototypes without having to see the code) I know that some compilers will often try to optimize compile time by skipping files that have not been modified. Since the header file isn''t compiled it is included you can encounter the scenario where you update a header file but not the cpp file that includes it, and thus the compiler thinks that the code has not been changed and doesn''t recompile the file. In other words, your changes won''t be compiled until you make a change in the cpp file.

Typically if you keep the implimentation out of the header file, if you make changes to the header file you are going to make changes to the file which contains the implimentation, and thus it will be recompiled.

Share this post


Link to post
Share on other sites
Putting the implementations of functions in the headers makes them huge and cluttered. Also, some (old) compilers might try and inline some big functions that you put directly in the header, which could lead to huge executable sizes.
quote:

I hate to make a habit of these "multi-threads", but I have one more question for now. It''s just a basic question, verifying what I know about headers and source. Headers are concatenated to the beginning of the source they are included in prior to compile. When a function is called that has no implementation, it searches for the implementation. Here is my main question: where does it search? The source file of the same name? The entire body of files specified as being members of the project? Thanks.


The compiler goes through all the headers first, taking a note of what functions/classes were defined, then, when it reaches your code, if you don''t have it defined then it will spit out an error (this is both in c and c++, d, however, doesn''t have this problem and doesn''t even have forward declaration).
quote:

I know that some compilers will often try to optimize compile time by skipping files that have not been modified. Since the header file isn''t compiled it is included you can encounter the scenario where you update a header file but not the cpp file that includes it, and thus the compiler thinks that the code has not been changed and doesn''t recompile the file. In other words, your changes won''t be compiled until you make a change in the cpp file.


The compiler compiles every single file that you give it. What your talking about is the job of the ide (if any). Most IDE''s I know will re-compile all source files that include a header that has been modified. Pretty much the only time that ever happens is when you aren''t using an ide (ie unix programming and some hardcore windows programmers *cough*me*cough* ) then sometimes you forget to delete an object file (what the cpp file is compiled into) after you modify it, which can cause bugs. But, if you only modify the private part of a class than you only have to recompile the source file that has the implementations of the functions in it.

Share this post


Link to post
Share on other sites
Rellik,

The others basically summed up why you should seperate headers from souce files.

The other answer to your question (the last one) is during the compile process, it verifies syntax, makes sure you are calling all the functions correctly. After it completes that the compiler then creates pseudo-code in a special format in an .OBJ file (if you look in your debug/release directories you will see alot of these). If a function has no implementation (such as a header with no source file with code) there will be a location in the .OBJ file thats blank. During the linking process (you probably notice your code gets compiled, and after thats done, it gets linked) is tries to paste this .OBJ file stuff into the .EXE. Obviously the code compiled and it thinks there is a function there, but nothing is in the .OBJ file. That will trigger a linker error saying "Unresolved external symbol function_blahblahblah"... That basically means theres no source but a header entry being used. The function is listed there but the mess after the function name is the pseudo-code identifier in the .OBJ.

When you get a bit more advanced, you will run into .lib files. These are basically precompiled .OBJ files (or a collection of many sources .obj files) You can specify these .lib in the linker settings, and when your code is linked, it will take the .lib pseudo-code instead of needing a source file. Alot of the time in windows, you will include windows.h, but you link to many different files (gdi.lib). The reason people make .lib files is because you can compile using their code, but you can''t see their code, or change it. That way you can make windows programs without seeing the actual windows source code. Everything is tucked away in the .lib files.

Lets say there is a function in a .lib file that is also in your source. The linker will report an error "function is ambigious" meaning it can''t tell to either use your source or the .lib. That gets kinda sloppy. Thats why its usually wise to name your functions with a prefix. I use "BX". "BX_CreateWindow" instead of "CreateWindow" which is what Windows will use.

Hope that helps.

Share this post


Link to post
Share on other sites
Regarding the issue of changed header files not recompiling the corresponding source, you guys can just make a simple modification to the makefile for this. In the corresonding dependancies just make sure you include both the .cpp file and the .h file for the target. Like for example:


foobar.obj : foobar.cpp foobar.h
//compilation commands goes here


This way the target gets recompiled if either foobar.h or foobar.cpp gets changed.





--{You fight like a dairy farmer!}

Share this post


Link to post
Share on other sites