Thread: I keep seeing some advice.. (Header file related)

  1. #1
    Registered User
    Join Date
    Aug 2004
    Location
    San Diego, CA
    Posts
    313

    I keep seeing some advice.. (Header file related)

    ..but I don't quite understand the purpose behind it. I often see, when people give advice, a direction to prototype functions in somefile.h and then put the actual functions in somefile.cpp. I'm just wondering what the purpose of this is - Wouldn't the code compile fine if it's all packed in the header file, or am I missing something?

  2. #2
    yes, I'm registered!!! algi's Avatar
    Join Date
    Nov 2004
    Location
    Ipswich
    Posts
    161
    putting other files in helps to maintain the programme code easier
    I started out with nothing and I still have most of it left.

  3. #3
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    if you compile the .cpp files you can just include the header in your program and pass the .obj to the linker, thus speeding up recompilations tremendously.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  4. #4
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    Wouldn't the code compile fine if it's all packed in the header file, or am I missing something?
    Besides the reasons mentioned above, *perhaps* you might run into function redefinition errors.. not sure if that's a linker or compiler thing or both, but if it's a linker thing then if you have the same function defined in multiple .cpp files (i.e. defined in a .h file and then included into multiple .cpp files), the linker might complain. I'll run a test in a sec...

    **EDIT**
    Yes, you'll get errors:
    test1.obj : error LNK2005: "void __cdecl doSomething(void)" (?doSomething@@YAXXZ) already defined in main.obj
    test2.obj : error LNK2005: "void __cdecl doSomething(void)" (?doSomething@@YAXXZ) already defined in main.obj
    The header file, test.h, is:
    Code:
     #ifndef TEST_H_
     #define TEST_H_
     void doSomething()
     {}
     #endif
    And each of test1.cpp and test2.cpp have a single line:
    Code:
     #include "test.h"
    Last edited by Hunter2; 01-12-2005 at 06:12 PM.
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  5. #5
    Registered User
    Join Date
    Nov 2004
    Posts
    17
    Quote Originally Posted by Lithorien
    ..Wouldn't the code compile fine if it's all packed in the header file..
    no, you can not compile a header file alone, so don't think of it as a code file. If you were going to use only 1 file then it would be in somefile.cpp.. -a code file. But, if you need to use some code here, then a header should come into play.

    Along with the posts previously mentioned, a header file can be used to expose the desired functions, variables, or perhaps classes, that are defined within the code file. You can expose them to outside usage so that other compilation units can have usage to the stuff.

    Generally, in a more OOP oriented posture you would want to write up the header so that perhaps only the other people(or code) who need to use specific functions would see it. So you don't just put all references the everything in the header, but only what should be relevant on the outside.. -so this is the "interface".

    Maybe in a C fashion you would have 10 code functions and some global variables, where only 4 functions need to be called from outside code to get at the functionality, and the rest just call around between each other. In this case, you could have a header with all 10 function declarations as well as the globals, or it would also be an okay choice to only have the 4 functions listed in the header.

    Used in a fashion as Sebastiani mentioned you might have previously compiled 4 useful code files(and hence have their respective .obj files) and decide to right 1 header that encapsulates all that functionality into 1 mere header.

    Here's a rough example(non OOP), let's say you write a compilation unit that retrieves the current time and does some specific formatting for it into a char string. On the 'outside', all you need access to is the 1 main function that handles the whole scheme, and let's say some global variable that has some useful meaning for something. Here's the 2 files:

    Code:
    //custom time getter header file
    //custimget.h
    
    
    extern int count;//pretend this would be useful to the outside
    
    int GetFormattedTimeString(char* buf);
    Code:
    //custom time getter code file
    //custimget.cpp
    
    #include "custimget.h"
    
    
    int count = 0;
    int somethingusefultoo;
    
    void DoSomeFormatting(void);
    int DoAnything(char* buf);
    int GetFormattedTimeString(char* buf);//notice this
    int GetFormattedTimeString(char* buf);//notice this
    
    
    int GetFormattedTimeString(char* buf)
    {
        //blah blah
        DoSomeFormatting();
        return DoAnything(buf);
    }
    
    
    void DoSomeFormatting(void)
    {
        int something;
        //some support code
        //blah blah
        count += something;
    }
    
    
    int DoAnything(char* buf)
    {
        //blah blah
        return 1;
        //else
        return 0;
    }
    -the extern 'count' in the header is not a declaration and definition(like it is in the code file), it is a special case declaration. And in this example assumably it would have some usefulness to the outside, otherwise you wouldn't especially want it there.

    -You generally don't want to outright declare anything in the header if you plan to include that header elsewhere(because it will already be included into it's code file so during linkage you'd have an issue about it being multiply defined).

    So, this example could be easily used by merely including the header into the file where you need to use the code.. -matter of fact you could include this header into multiple files of your project without any problems, because there are no real declaration definitions.

    The topic is a broad area, because really it comes down to programming styles, and the situation, but hope that helps as far as some basics.
    Last edited by zcot; 01-13-2005 at 04:59 PM.

  6. #6
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    matter of fact you could include this header into multiple files of your project without any problems, because there are no real declaration definitions.
    This is, in fact, the main reason why you'd want to do it that way. Simply because if you define the functions in the header as opposed to only prototyping, you'll get linker errors if you include the header in more than one file.

    The topic is a broad area, because really it comes down to programming styles, and the situation
    Unless you're creating a template function, I can't think of any situation where it would be a 'good' idea to define a function in a header. No matter what, if you do that then you'll be limited to including the header in one .cpp file, which pretty much defeats the purpose of a header in the first place.
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  7. #7
    Toaster Zach L.'s Avatar
    Join Date
    Aug 2001
    Posts
    2,686
    The most practical reason is the one Sebastiani mentioned. I'll elaborate a bit on it:

    Note, this is a bit simplified, but essentially correct.

    Say you've broken a particular piece of functionality (a class, set of functions, whatever) into a header code.h and a source file code.C(or .cxx or .cpp, whatever, they're all just text files). Now, the declarations are all in code.h and the definitions are all in code.C. You then compile, creating the file code.obj (again, this may have a different extension depending on the compiler, but it is a compiled binary file). So, wherever you use this functionality, you include the declarations (#include "code.h") so that the compiler can do its job making sure that you have all your calls properly matched up. When you compile these other files, however, they will simply reference the appropriate code in code.obj, and the linker takes care of resolving these external symbols (as a side note, you can now easily see where the dreaded "unresolved external errors" come from). Now, you decide to modify the implementation of one of your functions, so you open up code.C, and modify it. The only file dependent on code.C (the implementation) was code.obj, so only it needs to be recompiled, and then all that remains is for your program to be relinked. (Note that the declarations did not change.)

    Now, if you implemented it all in code.h, anything that included code.h must also be recompiled, which can take a whole lot of time on big projects, and then of course, everything must be relinked as well.

    Also note, if you want to distribute a library in a non-open source manner, then you would essentially provide only the headers and the object files, and so the implementation files would never be seen by anyone.

    Cheers
    The word rap as it applies to music is the result of a peculiar phonological rule which has stripped the word of its initial voiceless velar stop.

  8. #8
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    anything that included code.h must also be recompiled, which can take a whole lot of time on big projects, and then of course, everything must be relinked as well.
    So what about the linker redefinition errors that pop up? Or do they only appear when the linker is in a bad mood?
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  9. #9
    Toaster Zach L.'s Avatar
    Join Date
    Aug 2001
    Posts
    2,686
    I can't say I've run into them. So long as you have inclusion guards, there isn't any reason why you should have problems.

    As an amusing anecdote, I remember looking on in horror a few years ago when I took C++ as AP Comp Sci, and upon downloading the apstring class, I found the follwing:
    Code:
    #ifndef APSTRING_H
    #define APSTRING_H
    
    class apstring {
       // Blah, blah, blah...
    };
    
    #include "apstring.cpp"
    
    #endif
    The word rap as it applies to music is the result of a peculiar phonological rule which has stripped the word of its initial voiceless velar stop.

  10. #10
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    >>I found the follwing:
    I remember DavidP advocating this approach at one point

    >>I can't say I've run into them. So long as you have inclusion guards, there isn't any reason why you should have problems.
    Well, I ran into problems with the linker, using MSVC 2005 (although that's supposedly beta, it seems fully functional to me). The errors I got are posted above. Perhaps the errors wouldn't have existed if the hashed-up internal function names were different in each of the compiled .obj files, but apparently they weren't (and I'm not sure if they were ever supposed to be) so I got linker problems. It makes some sense too; the compiler doesn't see all the .cpp files together, so it has no way of knowing that the function has already been defined in another object. But then, suppose the linker finds a reference to a function called 'test()' which happens to be defined in two different object files that it's linking together - we'll have an ambiguity.
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  11. #11
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Functions with external linkage must not be defined in multiple translation units. Exceptions are template instantiations and inline functions (which, I believe, no longer have static linkage after some addendum to the standard).

    A translation unit consists of a single main source file (usually .cpp or .cc file extension) and all the code directly and indirectly in it.

    This means that if you have definitions in header files, and include these from two different source files, the definitions show up in the resulting two translation units. This is not legal.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Newbie homework help
    By fossage in forum C Programming
    Replies: 3
    Last Post: 04-30-2009, 04:27 PM
  2. Checking array for string
    By Ayreon in forum C Programming
    Replies: 87
    Last Post: 03-09-2009, 03:25 PM
  3. Class methods in header or source file?
    By TriKri in forum C++ Programming
    Replies: 13
    Last Post: 09-17-2007, 05:23 AM
  4. Unknown Memory Leak in Init() Function
    By CodeHacker in forum Windows Programming
    Replies: 3
    Last Post: 07-09-2004, 09:54 AM
  5. Replies: 6
    Last Post: 04-02-2002, 05:46 AM