Thread: Class methods in header or source file?

  1. #1
    Algorithm engineer
    Join Date
    Jun 2006
    Posts
    286

    Class methods in header or source file?

    Where is the best place to put the class methods? Directly in the class in the header file, if you are developing a library, or in an external source file?

    The reason to have them directly in the header file is that you can have a header file only and no source file, so you get only one file. Besides, isn't it more complicated to have another source file to compile, you'll have to make a project file linking all the source files and the header files together, right?

    On the other hand, I know some people think that there should be no functions, no methods or any executable code whatsoever in header file, that code should be in source files. This is making me a little unsure what is really the best place to put the methods. Is there any standard or is it up to the programmer? Does it depend on the size of the project one is developing? Or is it completely up to the programmer? Is there anything I haven't thought of?
    Come on, you can do it! b( ~_')

  2. #2
    Registered User
    Join Date
    Oct 2001
    Posts
    2,129
    they go in source file unless they are inline.

  3. #3
    Registered User
    Join Date
    Oct 2006
    Posts
    118
    Quote Originally Posted by robwhit View Post
    they go in source file unless they are inline.
    Isn't it all source file? :P

    FlyingIsFun1217

  4. #4
    Registered User
    Join Date
    Nov 2006
    Posts
    519
    the funny thing is: before the compiler does it's job, the preprocessor does run. And one of the things it does all the time is copying the content of the header into the .cpp which includes the header. and the compiler finally only looks at the .cpp. So it doesn't matter.
    But there are at least two special cases I know of:
    1. template code in .cpp files can generate linker errors with some linkers
    2. singletons used from inside DLL's shouldn't be implemented inside the header or they will end up as "multiples"

  5. #5
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    When a header that contains implementations is included by two source files, you've got a problem: the implementations are compiled twice, and the linker gets confused.

    Unless the linker takes special care. But in C++, it only takes special care for inlined functions and template instantiations. Out-of-line implementations of normal functions must therefore be in normal source files.
    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

  6. #6
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Also, for libraries that you sell to customers, you don't want to give them your source code. Only give them a header file with the function declarations, but no definitions, and a .lib or DLL file...

  7. #7
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    If they're template libraries, you don't have a choice, you know ...
    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

  8. #8
    Registered User
    Join Date
    Oct 2001
    Posts
    2,129
    file1.h
    Code:
    #include "lib.h"
    
    void func1(void);
    file2.h
    Code:
    #include "lib.h"
    
    void func2(void);
    file1.c
    Code:
    #include "lib.h"
    
    void func1(void)
    {
        libfunc("heoisdjfls");
        
        return;
    }
    file2.c
    Code:
    #include "lib.h"
    
    void func2(void)
    {
        libfunc("heoisdjfls");
        
        return;
    }
    lib.h
    Code:
    #include <stdio.h>
    
    int libfunc(char *p)
    {
        puts (p);
    
        return 0;
    }
    main.c
    Code:
    #include "file1.h"
    #include "file2.h"
    
    int main()
    {
        func1();
        func2();
        return 0;
    }
    Code:
    C:\>gcc -c file1.c -o file1.o
    
    C:\>gcc -c file2.c -o file2.o
    
    C:\>gcc -c main.c -o main.o
    In file included from file2.h:1,
                     from main.c:2:
    lib.h:5: error: redefinition of 'libfunc'
    lib.h:5: error: previous definition of 'libfunc' was here
    
    C:\>

  9. #9
    Algorithm engineer
    Join Date
    Jun 2006
    Posts
    286
    What if you protect lib.h against double inclusion? By the way, what do o-files contain? Have they already been run through the precompiler or are they gonna?
    Come on, you can do it! b( ~_')

  10. #10
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    Even if you add header include guards, the error will still occur because file1.c and file2.c are compiled separately.

    The .o file comes from after a source file has been compiled, but before it is linked with the other .o files to make the executable. Providing the header files and .o files for a given platform should be enough to allow a user of your library to use your library. Sometimes the .o files are combined into a library file (like .lib or .so I think) so that you only have to send one file instead of a .o file for each source.

  11. #11
    Algorithm engineer
    Join Date
    Jun 2006
    Posts
    286
    So that's why you should have only declarations and no definitions in header files. A function in a header file that is included more than once leads to confusion for the linker. But what about class definitions in a header file that is included twice? Doesn't that lead to confusion as well?
    Come on, you can do it! b( ~_')

  12. #12
    Registered User
    Join Date
    Oct 2001
    Posts
    2,129
    What if you protect lib.h against double inclusion?
    when you use a makefile, then you would have to recompile every file that the header file is included in whenever you make an implementation change. so it's not a good idea anyway.
    Code:
    C:\>gcc -c file1.c -o file1.o
    
    C:\>gcc -c file2.c -o file2.o
    
    C:\>gcc -c main.c -o main.o
    
    C:\>gcc main.o file1.o file2.o
    file1.o(.text+0x0):file1.c: multiple definition of `libfunc'
    main.o(.text+0x0):main.c: first defined here
    file2.o(.text+0x0):file2.c: multiple definition of `libfunc'
    main.o(.text+0x0):main.c: first defined here
    collect2: ld returned 1 exit status
    
    C:\>
    By the way, what do o-files contain?
    the object files have compiled, but not linked, code.
    Have they already been run through the precompiler or are they gonna?
    they already have, before the compiler.

    and it's a preprocessor.
    Last edited by robwhit; 09-16-2007 at 06:28 PM.

  13. #13
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> But what about class definitions in a header file that is included twice?
    No, because a class definition is really just a declaration of what that class looks like and the compiler and linker know that a class defined once is the same as a class defined again with the same name in another compilation unit.

    This actually can lead to unintended errors if you have two classes with the same name declared in separate header files and no source files include both headers.

  14. #14
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Which is known as the "One Definition Rule" (ODR), an evil beast. The ODR says that there must be only one distinct definition of any given entity in a C++ program, but that such errors need not be diagnosed. That's because it's very hard to do. Consider:
    foo.cpp:
    Code:
    class ODR
    {
    public:
      char muchdata[100];
    };
    
    void foo(ODR *p)
    {
      strcpy(p->muchdata, "Hello, there, how are you?");
    }
    bar.cpp:
    Code:
    class ODR
    {
    public:
      int littledata;
    };
    
    void foo(ODR *p);
    
    int main()
    {
      ODR odr;
      foo(odr);
    }
    This program will compile, because the ODR violation of the ODR class is usually not detected, but it will crash at runtime, because the compiler gave the odr variable in main() sizeof(int) bytes, but foo will write far more bytes than that into this space, thus trashing the stack.
    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. Replies: 3
    Last Post: 02-10-2009, 02:51 PM
  2. To find the memory leaks without using any tools
    By asadullah in forum C Programming
    Replies: 2
    Last Post: 05-12-2008, 07:54 AM
  3. Message class ** Need help befor 12am tonight**
    By TransformedBG in forum C++ Programming
    Replies: 1
    Last Post: 11-29-2006, 11:03 PM
  4. simple class with header file
    By Unregistered in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2001, 08:14 PM