Search

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, having all the member function definitions inside the class can make 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 member function 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 definition. 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 resolution 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 definition, 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 that includes an externally defined constructor with a member initialization list:

becomes:

Putting class definitions in a header file

In the lesson on header files, you learned that you can put function declarations inside header files in order to use those functions in multiple files or even multiple projects. Classes are no different. Class definitions can be put in header files in order to facilitate reuse in multiple files or multiple projects. Traditionally, the class definition 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.

Doesn’t defining a class in a header file violate the one-definition rule?

It shouldn’t. If your header file has proper header guards, it shouldn’t be possible to include the class definition more than once into the same file.

Types (which include classes), are exempt from the part of the one-definition rule that says you can only have one definition per program. Therefore, there isn’t an issue #including class definitions into multiple code files (if there was, classes wouldn’t be of much use).

Doesn’t defining member functions in the header violate the one-definition rule?

It depends. Member functions defined inside the class definition are considered implicitly inline. Inline functions are exempt from the one definition per program part of the one-definition rule. This means there is no problem defining trivial member functions (such as access functions) inside the class definition itself.

Member functions defined outside the class definition are treated like normal functions, and are subject to the one definition per program part of the one-definition rule. Therefore, those functions should be defined in a code file, not inside the header. The one exception for this is for template functions, which we’ll cover in a future chapter.

So what should I define in the header file vs the cpp file, and what inside the class definition vs outside?

You might be tempted to put all of your member function definitions into the header file, inside the class. While this will compile, there are a couple of downsides to doing so. First, as mentioned above, this clutters up your class definition. Second, functions defined inside the class are implicitly inline. For larger functions that are called from many places, this can bloat your code. Third, 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!

Therefore, we recommend the following:

  • For classes used in only one file that aren’t generally reusable, define them directly in the single .cpp file they’re used in.
  • For classes used in multiple files, or intended for general reuse, define them in a .h file that has the same name as the class.
  • Trivial member functions (trivial constructors or destructors, access functions, etc…) can be defined inside the class.
  • Non-trivial member functions should be defined in a .cpp file that has the same name as 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 definition (in the header file), where they can be seen by whomever #includes the header.

Libraries

Separating the class definition 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 single copy of a precompiled library can be shared by many applications, 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

143 comments to 8.9 — Class code and header files

  • hellmet

    On second thought, I've started to think, if I'm sending out precompiled libraries that are ready to be linked against, both the library and the code using it should be compiled on the same platform (this is obvious). But what about the compiler(s) (and versions of the same compiler!)? I have a feeling this matters. If or if not, how so?

    • Alex

      Precompiled libraries are already compiled -- and thus, the compiler you're using shouldn't matter.

      • hellmet

        Okay!

        I started thinking about this as I stumbled upon a warning, the solution to which suggested that I should run/link against the same runtime libraries. More specifically, I was trying out GLFW, VS was using its own version of the C++ runtime library (I'm guessing the std:: stuff is the runtime library) and GLFW was compiled with a different version.
        (https://stackoverflow.com/questions/3007312/resolving-lnk4098-defaultlib-msvcrt-conflicts-with answer by yochai)

        I think that's what happened. Please correct me if I'm wrong!

  • TheFutureCoder

    Hi nascadriver/Alex,
    I have a question about this line "Note that Date.cpp also needs to be compiled into any project that uses Date.h so the linker knows how Date is implemented.".
    I want to know how I can do this in visual studio.

  • Alex

    hi, thanks for the tutorial
    I've found similar here: http://www.math.uaa.alaska.edu/~afkjm/csce211/handouts/SeparateCompilation.pdf
    (i mean NOT copyright but same topic)
    But there he uses also different compilation line: g++ main.cpp Num.cpp
    and you not using this (you actualy not using main.cpp either, but still)
    Don't you wanna add something about "separate compilation" too?
    g++ -c main.cpp
    g++ main.o Num.o

    and also about #pragma once

  • Anastasia

    Hi!
    I'm getting a compilation error (error: ‘RGB’(‘CMYK’) does not name a type) when I'm trying to define my getters in the class' cpp (everything works fine when defining in the header). What's wrong?

    Color.h

    Color.cpp

    main.cpp

    And a couple questions about the implementation:

    Is it okay to have structs in a class or would it be better to have two separate classes in this case?

    It's unlikely that I'd want to change the implementation of the conversion functions (`RGBtoCMYK()` and `CMYKtoRGB()`) in every cpp and I wouldn't mind them being inlined. Should I've defined them in the header?

    • Please, when you get an error, also post line numbers.
      Color.cpp line 44, you're using `RGB`, but there is no `RGB`. At this point, you're not inside the class, so you have to return a `Color::RGB`.
      This leads you to your next problem. You declared the types privately, you can't use them on the outside.

      > Is it okay to have structs in a class or would it be better to have two separate classes in this case?
      When they're small and considered a part of the class it's ok to have them be members. Having an rgb and a cmyk member variable is wrong. A color will never have two different colors. You can fix this by renaming `Color` to "ColorConverter" or similar, or by choosing one internal representation which you convert whenever the other representation is accessed.

      > It's unlikely that I'd want to change the implementation of the conversion functions (`RGBtoCMYK()` and `CMYKtoRGB()`) in every cpp
      I don't understand. You only implement them once.

      > Should I've defined them in the header?
      No. Headers are for declarations.

      • Anastasia

        Sorry. Lines 44 and 49 in Color.cpp. Prefixing the return types with `Color::` fixed the error, thanks.

        > you can't use them on the outside
        But it seems that I can when prefixing them with the name of the class and having the header included or I can't?

        > Having an rgb and a cmyk member variable is wrong. A color will never have two different colors. You can fix this by renaming `Color` to "ColorConverter" or similar, or by choosing one internal representation which you convert whenever the other representation is accessed.
        The idea was that an instance can be initialized with either RGB or CMYK and the conversion to the other model will be done automatically (the constructor calls the setter which calls the converter). This prevents an instance having two different colors at the same time. I haven't thought much about the class' name I admit (it reflects this fact).

        > You only implement them once.
        But I can have different cpps (which may define the functions a bit differently) that use the same header, right? If one implementation will most likely stay the same it would make sense (to me) to keep it in the header.

        edit::a typo fixed

        • > But it seems that I can when prefixing them with the name of the class and having the header included
          Yes, but the caller can't create a `Color::RGB` or `Color::CMYK` to store the returned value.

          > The idea was [...]
          The second member variable doesn't add any extra information. You wouldn't store weight in grams and ounces or a message in binary and base64, because the two things are the same, just a different format. If you're in a high-memory, low-processing-power scenario, you can consider storing the data twice so you don't have to convert it.
          Otherwise it's best to choose the format that will be used more often as the internal representation and convert on-the-fly. Redundant storage increases potential inconsistencies due to human-error and increases the amount of work required to add something to the code (You have to do everything twice).

          > But I can have different cpps (which may define the functions a bit differently) that use the same header, right?
          No, there can only be one definition per function.
          Writing code in headers dramatically slows down re-compilation and quickly leads to circular dependencies.

          • Anastasia

            > Yes, but the caller can't create a `Color::RGB` or `Color::CMYK` to store the returned value.
            Right, that was silly. I've put the structs outside the class in the header, namespaced all together. I hope it is okay to do so?

            > ... Redundant storage increases potential inconsistencies due to human-error and increases the amount of work required to add something to the code (You have to do everything twice).
            At this point I'm not trying to write efficient code, just code that works and does something (I barely manage even that). But I got what you mean.

            > No, there can only be one definition per function.
            There will be just one. One time I compile `main1.cpp Color1.cpp` both including `Color.h`, next time I compile `main2.cpp Color2.cpp` including same header, but `Color2.cpp` happens to define some functions differently. Doesn't this make sense at all?

            > Writing code in headers dramatically slows down re-compilation and quickly leads to circular dependencies.
            Got it, I'll try to avoid doing that.

            • > I hope it is okay to do so?
              I'd have kept them in `Color`, but public, because I like `Color::RGB` and `Color::CMYK`. It's up to you though, do what you like.

              > Doesn't this make sense at all?
              You're going in the direction of interfaces. An interface declares the functions a class has, but not its members or implementation. Then you'd still have 2 headers and 2 source files (One for each Color1, one for Color2), but you could write functions without caring which color comes in.
              What you said can be useful for prototyping or conditionally compiled code (eg. Color1 for linux, Color2 for windows), but I don't see a use for it in this case.

              • Anastasia

                I'm just trying to grasp the concept of the separation of a project into different files in general, not this case specific. Thank you so much for clearing things up, I can't even express how much it helps me!

  • McDidda

    Hi,
    Can you tell where you talked about "classes in two separate headers and using definitions of each other", I read that page recently but cannot find the same again.

  • cdecde57

    So I finished the lesson but I am confused on 1 part of it. Declaring the member functions outside the class. What essentially happens? Like why not just keep them all inside and when would you want to make them outside?

    I can imagine putting the constructors or destructors outside to put in like a cpp file or something but anyway's I am just wondering when and why put them outside and is it important to get used to doing?

    • Declare classes in header files, define them in source files.
      Defining them in the header exposes the definition to the user of the class, even if they just need the declarations. Definitions in headers often lead to circular includes.
      In these tutorials, they're often defined in the header to keep the code shorter, you shouldn't do that in practice.

  • Nguyen

    Hi,

    I have a question in the third example.

    becomes:

    Thanks

  • Louis Cloete

    I just read this interesting post: https://www.acodersjourney.com/top-25-cplusplus-api-design-mistakes-and-how-to-avoid-them/ Maybe you can link to it in this lesson or incorporate some of its suggestions?

    • Alex

      Yep, good suggestions there. I'll have a closer read and figure out how to incorporate any worthwhile insights as part of the lesson rewrites. Thanks!

  • Andrew

    I want to define an .h and an .cpp file for represent a spare matrix as a dynamic array containing triples <line,column,value> ordered lexicographically.I write here both files(Matrix.h and after Matrix.cpp)

    Matrix.cpp

    I work in VS2017 and I obtain some errors.I guess that they appears because I cannot acces the private elements from the header file.Some ex of errors:
    Error    C3867    'Matrix::n': non-standard syntax; use '&' to create a pointer to member
    Error    C2597    illegal reference to non-static member 'Matrix::m'
    Error    C3867    'Matrix::arr': non-standard syntax; use '&' to create a pointer to member
    Error    C2568    '>=': unable to resolve function overload
    Error    C2109    subscript requires array or pointer type

    Each of these appears several times.
    Thanks!

    • @Matrix::element is declared const, but not defined const (Add const in the cpp file).
      @Matrix::element is trying to access this.numberOfEl(), but @this is a pointer, use this->numberOfEl().
      There are more issues with your code, make sure you followed lesson 0.10 and 0.11.

  • Gizmo

    Thanks to Nascardriver for answering my last question. My question now is if it's possible to define a private function outside the class in the header/.cpp format.

    I'm doing the quiz at the end of the chapter (spoilers) and I'm supposed to have a random number generator function as a private member function.

    This is the snippet from the answer's code:

    The problem is that I want to turn this into a header/.cpp format, but since it's a private member, I don't know how I could go about doing that. Is it at all possible to declare getRandomNumber in the header and then define it in the .cpp file?

  • Gizmo

    I have a question relating to constructors and headers. How do you create a constructor that initializes an array using a loop at the same time?

    For example, look at the following code:

    How would you reorganize this into a header/.cpp format?

    Note: this is just a small example code of what I am trying to do, for simplicity's sake. Some projects I'm working on require arrays of entire classes to be initialized, which make the initialization coding a lot more cumbersome.

    • > How do you create a constructor that initializes an array using a loop
      You can't. If you want to initialize the array, you need to do so with fixed values. If you want to use a loop, you can only assign values.

      > How would you reorganize this into a header/.cpp format?

  • pete

    Hi Alex,
    the Date class example from "Putting class definitions in a header file" part of this chapter works a described.
    However, trying to separate the member function's definitions from the .cpp file (where main() is) to a different .cpp file (which contains only the function's bodies for that matter) causes a bunch of errrors which brings up few questions. First, is it possible to separate the member function's definition code from the main().cpp file and if it is, is there any reason to do so? Second, how do you #include a .cpp file?
    thanks!

    • > is it possible to separate the member function's definition code from the main().cpp file
      Yes

      > is there any reason to do so?
      Yes, it makes your code readable. Having everything in one file is a mess.

      > how do you #include a .cpp file?
      You don't. You include the header file. If you're using an IDE, the source files should get compiled automatically. If you're compiling manually, you have to add the new cpp file to the files to be compiled.

      • pete

        thank you for nascardriver,
        i've modified the program so the function's definitions are in a separate .h file of their own. however i've noticed it only works when i #include the Class's .h file AND the member function's bodies .h file both in the main().cpp file. It doesn't work if you #include the function's definitions file in the class's file and then #include only the class .h file in the main().cpp file (actually, chaining the header files).
        Moreover, it doesn't even matters whether you #include the class's .h file in the function's definitions .h file or not. I would expect the compiler to throw an error since theres no relevant identifier in that file.
        i was hoping if you could elaborate on the linking infrastructure behind these issues.
        thanks

        • myClass.hpp

          myClass.cpp

          main.cpp

  • Irishman

    I got a problem...first here is my code:

    Well the function printOakText does simply print the text to the console with a Sleep(75) after every letter, like in the pokemon-games. After printing some text, I want to know the playername. The problem is when I press some letters on my keyboard while the text is printing, it stands automatically after your name... Like this -> Your name: Hello Hello is what I typed while the text gots printed. How can i delete this? If I hit enter while my text is printing it would skip the input :( Need some help, thanks!

  • Andi

    Minor typo under Libraries:
    "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."

    should be: [...] library ARE contained [...]

  • TC

    Hi Alex,

    I have to say that your tutorial has been very helpful.  

    Well, for this chapter, I am trying to understand the following sentence.

    2) a precompiled library can be distributed once, whereas compiled code gets compiled into every executable that uses it (inflating file sizes)

    Can you elaborate more on "...can be distributed once"? Does it mean that the precompiled library can only be distributed once?

    Thank you

    • Alex

      I'm really speaking to shared libraries, which can be shared by multiple applications. I've updated the sentence to read, "a single copy of a precompiled library can be shared by many applications, whereas compiled code gets compiled into every executable that uses it (inflating file sizes)"

  • Hi, I just completed my FooTon class experiment.  The complete code is

    but the call to myage.print() just results in garbage.  Am I missing something here?

    • Hi Nigel!

      @Ton::Ton doesn't do anything. It contains a forward declaration for a function that doesn't exist. You're seeing garbage, because you didn't initialize @m_age.

  • Hi, I borrowed your date() class and put it into Foo.h and Foo.cpp thus:

    but it just tells me that cout is not a member of std and cout: undeclared identifier.

    • ah, hang on, I just changed the Foo.h file to this:

      It now woks as expected but isn't it bad practice to include an header file within an header file?

      • Hi Nigel!

        Header files should include as few other files as possible, because it will slow down compilation and possible cause circular dependencies or redefinitions. The bad practice in your/Alex' code is having definitions in the header file. Moving @print into @Foo.cpp gets rid of the include in @Foo.h.
        The only two reasons to have definitions in a header I can think of right now are templates (Chapter 13) and inline functions (Lesson 7.5).

  • Ken Matson

    Hi - love your tutorials!

    I'm trying to understand why I can't forward declare a class?

    my code ...

    This also happens if Foo is in it's own cpp file, which is what I really want. I'm trying to avoid having to split classes between .cpp and .h for single use classes. Do I just have to put it all in a .h and include it? No way to do it from a .cpp? I'm a newbie and appreciate any help!

    Thanks,
    KenM

    • nascardriver

      Hi Ken!

      Your example doesn't need a forward declaration, you can just move @main below @Foo.

      > Do I just have to put it all in a .h and include it?
      If you don't want to do it properly (splitting in header and source) you can do it like this. It shouldn't cause problems as long as there's just the class (without static members) in the header.

      In order to declare a variable of type @Foo the compiler needs to know the size of @Foo. With a simple forward declaration like you have this is not possible. You'd need to have all member declarations in the forward declaration.

      • Ken Matson

        Appreciate it - so to keep a class in its own single file - I have to use a .h and NOT the .cpp then? I guess i'm just hoping for java like syntax where I can say - "Ok here's where the definition of this class is - so use it" - regardless of the file type.

        THANKS!

        • nascardriver

          > I have to use a .h and NOT the .cpp then?
          If you really don't want to do it the right way, yes. This is not the same as splitting the code in header and source files. You're going to run into problems at some point. But for the most part this will work.

  • David

    Hi! I'm having trouble understanding this part:

    "types are exempt from the rule that a definition can only exist in one place"

    My compiler complains if I define two classes with the same identifier. Thus the following code won't compile:

    But it's ok for me to define class A in different files within the same project. Is that because user-defined types only have internal linkage? So it's not that classes are exempt from the one definition rule, its that each definition is file-specific?

    • Alex

      The one definition rule (ODR) states that types can only be defined once per file, but can be defined many times per program, as long as the definitions are identical. I'll sharpen the language to make sure this is clearer.

  • Dekasi

    Hi Alex. I was looking for what the term one-definition rule means, but I could not find it. can you tell me in which section it is explained? Thank you in advance.

  • Walter

    Thanks for this tutorial, it is great!
    Here my question: Why should the private varaibles stay in the header file?
    I tried to put them into the cpp, but didn't succeed to make them part of the class, they always ended up as global variables and not as private ones.

    • Alex

      All member variables (private or otherwise) need to be declared as part of the class definition. I'm not sure what it would mean to put them in the .cpp.

  • I relish, lead to I found just what I used to be having a look for.

    You have ended my 4 day long hunt! God Bless you man. Have a great day.
    Bye

Leave a Comment

Put all code inside code tags: [code]your code here[/code]