Search

Language Selector

8.9 — Class code and header files

Defining member functions outside the class definition

All of the classes that we have written so far have been simple enough that we have been able to implement the member functions directly inside the class definition itself. For example, here’s our ubiquitous Date class:

However, as classes get longer and more complicated, mixing the declaration and the implementation details makes the class harder to manage and work with. Using an already-written class only requires understanding its public interface (the public member functions), not how the class works underneath the hood. The implementation details just get in the way.

Fortunately, C++ provides a way to separate the declaration portion of the class from the implementation portion. This is done by defining the class member functions outside of the class declaration. To do so, simply define the member functions of the class as if they were normal functions, but prefix the class name to the function using the scope operator (::) (same as for a namespace).

Here is our Date class with the Date constructor and setDate() function defined outside of the class definition. Note that the prototypes for these functions still exist inside the class declaration, but the actual implementation has been moved outside:

This is pretty straightforward. Because access functions are often only one line, they are typically left in the class definition, even though they could be moved outside.

Here is another example:

becomes:

Putting class definitions in a header file

In the lesson on header files, you learned that you can put functions inside header files in order to reuse them in multiple files or even multiple projects. Classes are no different. Class declarations can be put in header files in order to facilitate reuse in multiple files or multiple projects. Traditionally, the class declaration is put in a header file of the same name as the class, and the member functions defined outside of the class are put in a .cpp file of the same name as the class.

Here’s our Date class again, broken into a .cpp and .h file:

Date.h:

Date.cpp:

Now any other header or code file that wants to use the Date class can simply #include "Date.h". Note that Date.cpp also needs to be compiled into any project that uses Date.h so the linker knows how Date is implemented.

You might be tempted to put both your class declaration and implementation into the header file. While this will work (and is fine for trivial classes), it is not recommended, as there are a couple of downsides. First, your class implementation code will be copied into every file that #includes it, and get recompiled there. This can be slow, and will cause bloated file sizes. Second, if you change anything about the code in the header, then you’ll need to recompile every file that includes that header. This can have a ripple effect, where one minor change causes the entire program to need to recompile (which can be slow). If you change the code in a .cpp file, only that .cpp file needs to be recompiled!

Rule: Put class declarations in a .h file, and non-trivial member function implementations in a .cpp file, both named after the class.

In future lessons, most of our classes will be defined in the .cpp file, with all the functions implemented directly in the class definition. This is just for convenience and to keep the examples short. In real projects, it is much more common for classes to be put in their own code and header files, and you should get used to doing so.

Default parameters

Default parameters for member functions should be declared in the class declaration (in the header file), where they can be seen by whomever #includes the header.

Libraries

Separating the class declarations and class implementation is very common for libraries that you can use to extend your program. Throughout your programs, you’ve #included headers that belong to the standard library, such as iostream, string, vector, array, and other. Notice that you haven’t needed to add iostream.cpp, string.cpp, vector.cpp, or array.cpp into your projects. Your program needs the declarations from the header files in order for the compiler to validate you’re writing programs that are syntactically correct. However, the implementations for the classes that belong to the C++ standard library is contained in a precompiled file that is linked in at the link stage. You never see the code.

Outside of some open source software (where both .h and .cpp files are provided), most 3rd party libraries provide only header files, along with a precompiled library file. There are several reasons for this: 1) It’s faster to link a precompiled library than to recompile it every time you need it, 2) a precompiled library can be distributed once, whereas compiled code gets compiled into every executable that uses it (inflating file sizes), and 3) intellectual property reasons (you don’t want people stealing your code).

Having your own files separated into declaration (header) and implementation (code file) is not only good form, it also makes creating your own custom libraries easier. Creating your own libraries is beyond the scope of these tutorials, but separating your declaration and implementation is a prerequisite to doing so.

8.10 -- Const class objects and member functions
Index
8.8 -- The hidden “this” pointer

32 comments to 8.9 — Class code and header files

  • Sam

    Hi,
    I’m having some trouble with what seems like using class in the class I’m writing.

    This is the header file:

    #ifndef GUEST_H
    #define GUEST_H

    using namespace std;

    class Guest {

    private:

    string Name, Addr1, Addr2, Phone;
    int Smoking, Pets; //0=none

    public:

    // default constructor
    Guest() ;

    // destructor
    ~Guest() ;

    //…other member functions…

    };

    #endif

    The problem is, the compiler doesn’t seem to recognize when a member function tries to use Name. I’ve tried inserting std::string instead of string for the initialization, but that didn’t seem to work.

    Thanks

  • Deepu

    I think thr is another advantage of seperating implementation from defention in header files and cpp files.

    Suppose you are writing a Application Programming Interface ( a DLL or .so file) which your clients would be using, you normally give them the header files and the dynamic link libraries. As long as the signature of the methods defined in the interface does not change your client can make use of your diffrent vesions of your API. Also this is a good idea as you dont need to expose your source code to your client exposing all methods available in the API and a users manual on how to use them.

  • stephen

    what is the point of constructors? they are a waste of time to me, i just allocate the variables int the class

    • The point of constructors is to initialize the members of your class when the class object is created.

      There is no other way to initialize constant members of a class, for example.

  • cpp_beginner

    Hi!
    It’s a good idea to put classes and other functions in header files but can we put them in a .dll file?If so,can you make a short tutorial of how to make a Dinamic Link Library in VC++ 08??

  • Phil

    I just tried writing my own Date class using separate files, but using default parameters for the constructor
    . I wasn’t sure if the default parameters should be in the date.h or date.cpp file (or both). With a little t
    rial and error, discovered that the default parameters should go in the header file only. Maybe this should b
    e mentioned in the tutorial?

    By the way - Fantastic tutorial :-)

  • hakaye azure

    Hi…

    Thanks for the tutorial pages, it is magnificent.

    I have a problem over here:

    mymath.h

    mymath.cpp

    mymathtest.cpp

    compile result an error messages:
    Unresolved external ‘mymath::~mymath()’ referenced from [folder]mymathtest.obj
    Unresolved external ‘mymath::mymath()’ referenced from [folder]mymathtest.obj
    Unresolved external ‘mymath::mult(int, int)’ referenced from [folder]mymathtest.obj

    I work around this problem for hours (not the same code but the same idea), I don’t know where the codes went wrong
    and the last trial and error solve the problem, by adding a single line at the bottom of mymath.h, but is it the right way?

    • Gammerz

      You don’t need to add that last line of code in mymath.h

      Just add mymath.cpp to your project (I believe it gets linked in). I managed to get your original code working ok like this. Alex states:-

      Note that Date.cpp also needs to be compiled into any project that uses Date.h so the linker knows how Date is implemented.

  • In the second-to-last paragraph you said :
    “simply #include “Date.h”. Note that Date.cpp also needs to be compiled into any project that uses Date.h so the linker knows how Date is implemented. ”

    but why we didn’t include the Date.cpp file and the compiler knows where it is ,and compiles it? this confuses me for long time ,(i am a new C++ learner) Thanks Alex!

    By the way ,this tutorial is excellent,master piece! I want to work with you! Hah, but now I am a Chinese live in China. I longing US badly!

    • Alex

      It’s bad form to #include a .cpp file. C++ doesn’t disallow it, and in some cases (particularly simple ones) it will work, but in many cases you’ll end up running into problems, such as naming conflicts. Particular if you both #include a .cpp from another .cpp file AND put it in your project (in which case, the code will get compiled twice).

  • Clint

    If you have two different .cpp files that both have functions that use the <string> class, do you need to #include <string> in both of them?  If so, doesn’t it make things much less efficient to have all these different files that are all pulling from outside classes?    It seems like you also need to add #include "stdfx.h" and "using namespace std" to all the .cpp files (since I am using Visual Studio).

    Would it be better to keep things in one .cpp file so that you only have to #include outside files once?  Is the guideline still "one class, one file" even if your class member functions use a bunch of other libraries?  Thank you!

    • Jiri

      I think it has no effect on speed of compiled code - all header files have header guards, there will be no duplicates. You could speed up compilation a bit for sure, but the price for it is loss of modularity - you would not be able to withdraw a singl class without rewriting its header to include what it must in new project. One file would be a mess in bigger projects, How do you want to search for something in 10 000+ lines file ? It is better to search in header names.

      • Alex

        Jiri almost gets it right. Having multiple files may have an effect on compilation speed -- header files only prevent a header file from being #included more than once into the same includer. They do not prevent a header file from being included once each into many different files. A single header file that gets #included into 5 files will get compiled 5 times.

        That said, header files are typically just declarations, which compile quickly. The runtime speed won’t be impacted. The increase in organization and modularity is worth the small compilation time cost.

  • In the first example, why you wrote a default constructor that is private and not even calling any other function to set the initial value of member variable. Isn’t it redundant? I am talking about this line:

    • Alex

      Making a default constructor private means we can’t create objects that would use the default constructor for initialization. For example:

      In this case, we’re doing that because there isn’t really any good default value we should assume if the user doesn’t provide a date.

      This, in essence, forces the user to use one of the other constructors to create the object (and thus, provide default values for the object being created).

      • How much time would it take to me to think like you… :-) ??? You are just awesome.

      • Mekacher Anis

        in the lesson on constructors u said that if we declare any kind of constructor the compiler won’t create a default one so there is no need to make a default constructor private , just create one with arguments and no default parameters
        am I right ?

        • Alex

          You’d only need to make the default constructor private if you didn’t have any other constructors, and didn’t want people to instantiate objects of the class without parameters.

  • Banelus

    I’d like to know whether you recommend using include directives (e.g. #include <cstdint>, #include <iostream>) in header file with class declaration? I noticed it’s needed for std::cout, int32_t etc. What do you say?

    • Alex

      My take is that all files (whether code or header) should be responsible for #including the things that they themselves need to compile.

      For example, if a header file has an inline function that uses std::cout, that header file should definitely #include iostream.

      If a header file doesn’t use std::cout but it’s implementation file does, the implementation file should #include iostream.

      If a header file and an implementation file both use std::cout, then I typically have both #include iostream (even though the .cpp file doesn’t need to -- it will get a copy of iostream from the header). That way if the header file later changes and doesn’t need iostream any more, I don’t have to modify the implementation file, because it’s already self-sufficient.

  • Jiri

    main.cpp
    #include <iostream>
    #include "something.h"
    ---
    something.h
    #ifndef SOMETHING
    #define SOMETHING
    #include <iostream>
    #endif
    ---
    something.cpp
    #include "something.h"
    #include <iostream>

    Please correct me if i am wrong:
    - In compiled code there will be only one <iostream>, because it has header guard.
    - With prototype of every funcion i use in main.cpp i would not need any includes at all (in theory, i know its nonsense to do that)

    • Alex

      Header guards prevent a header file from being included more than once into the _same_ file. In the example above, main.cpp, something.h, and something.cpp will all have a _single_ copy of the declarations in iostream.

      Yes, if you did all of your forward declarations directly in main.cpp, you wouldn’t need to use a header, but you might as well use headers since they’re cleaner and can be shared.

  • Mr D

    I’m really failing to understand this chapter.

    I don’t understand the difference between class "definition" and "implementation".

    Your

    example is actually longer (32 lines) then the original (26 lines) and i don’t see the benefit. Are the functions that are moved outside now placed in

    ?

    To use the functionality of the class, you don’t need to look inside it at all do you? Isn’t that all done from

    ???
    I don’t see the reason to move anything outside. I thought the benefits of classes (mentioned earlier) is that they package things up nicely and keep stuff out of site, but in this lesson you’re recommending un-packaging them again!!

    Same thing with the class Calc example, the original seems nice and compact, the second version seems a lot longer and harder to read.

    I’m sure i’m just not getting something fundamental here. If possible, could you give a clear explanation of the difference between class "definitions" and "implementations"?

    • Alex

      The key passage for this lesson is this one: However, as classes get longer and more complicated, mixing the definition and the implementation details makes the class harder to manage and work with. Typically, when looking at a class definition (for an already written class), you don’t care how things are implemented -- you want to know how to use the class, which involves only its definition. In this case, all of the implementation details just get in the way.

      The benefit of classes is that they package up data and the functions that work on that data. Whether the functions are defined inside the class declaration or outside of it does not impact this.

      The original versions of the classes may seem more compact to you because the member functions are simplistic. However, in the case where the member functions become complex (imagine 100 lines each) putting all of those inside the class definition would make the definition long and complex.

      By definition, I really mean the class declaration, including the classes’s name, access specifiers, member variables, and member functions. The classes’s implementation includes the definition (body) for all the functions.

      Typically I use a mix of the two styles: If a function is only one line long, I typically keep it in the class declaration. If the function is more than one line long, I move it to the file that contains the implementation.

      There’s one other benefit to keeping your member function definitions in a separate file. If you change something in a function body, you only have to recompile that one file. If you change something in a class declaration (in a header file), you need to recompile EVERY file that #includes that header, which could be a large part of your project.

      Did this address your concern?

Leave a Comment

Put C++ code inside [code][/code] tags to use the syntax highlighter

  

  

  

4 × 5 =