11.2 — Classes and class members

While C++ provides a number of fundamental data types (e.g. char, int, long, float, double, etc…) that are often sufficient for solving relatively simple problems, it can be difficult to solve complex problems using just these types. One of C++’s more useful features is the ability to define your own data types that better correspond to the problem being solved. You have already seen how enumerated types and structs can be used to create your own custom data types.

Here is an example of a struct used to hold a date:

Enumerated types and data-only structs (structs that only contain variables) represent the traditional non-object-oriented programming world, as they can only hold data. In C++11, we can create and initialize this struct as follows:

Now, if we want to print the date to the screen (something we probably want to do a lot), it makes sense to write a function to do this. Here’s a full program:

This program prints:



In the world of object-oriented programming, we often want our types to not only hold data, but provide functions that work with the data as well. In C++, this is typically done via the class keyword. The class keyword defines a new user-defined type called a class.

In C++, classes and structs are essentially the same. In fact, the following struct and class are effectively identical:

Note that the only significant difference is the public: keyword in the class. We will discuss the function of this keyword in the next lesson.

Just like a struct declaration, a class declaration does not allocate any memory. It only defines what the class looks like.


Just like with structs, one of the easiest mistakes to make in C++ is to forget the semicolon at the end of a class declaration. This will cause a compiler error on the next line of code. Modern compilers like Visual Studio 2010 will give you an indication that you may have forgotten a semicolon, but older or less sophisticated compilers may not, which can make the actual error hard to find.

Class (and struct) definitions are like a blueprint -- they describe what the resulting object will look like, but they do not actually create the object. To actually create an object of the class, a variable of that class type must be defined:

Member Functions

In addition to holding data, classes (and structs) can also contain functions! Functions defined inside of a class are called member functions (or sometimes methods). Member functions can be defined inside or outside of the class definition. We’ll define them inside the class for now (for simplicity), and show how to define them outside the class later.

Here is our Date class with a member function to print the date:

Just like members of a struct, members (variables and functions) of a class are accessed using the member selector operator (.):

This prints:


Note how similar this program is to the struct version we wrote above.

However, there are a few differences. In the DateStruct version of print() from the example above, we needed to pass the struct itself to the print() function as the first parameter. Otherwise, print() wouldn’t know what DateStruct we wanted to use. We then had to reference this parameter inside the function explicitly.

Member functions work slightly differently: All member function calls must be associated with an object of the class. When we call “today.print()”, we’re telling the compiler to call the print() member function, associated with the today object.

Now let’s take a look at the definition of the print member function again:

What do m_year, m_month, and m_day actually refer to? They refer to the associated object (as determined by the caller).

So when we call “today.print()”, the compiler interprets m_day as today.m_day, m_month as today.m_month, and m_year as today.m_year. If we called “tomorrow.print()”, m_day would refer to tomorrow.m_day instead.

In this way, the associated object is essentially implicitly passed to the member function. For this reason, it is often called the implicit object.

We’ll talk more about how the implicit object passing works in detail in a later lesson in this chapter.

The key point is that with non-member functions, we have to pass data to the function to work with. With member functions, we can assume we always have an implicit object of the class to work with!

Using the “m_” prefix for member variables helps distinguish member variables from function parameters or local variables inside member functions. This is useful for several reasons. First, when we see an assignment to a variable with the “m_” prefix, we know that we are changing the state of the class instance. Second, unlike function parameters or local variables, which are declared within the function, member variables are declared in the class definition. Consequently, if we want to know how a variable with the “m_” prefix is declared, we know that we should look in the class definition instead of within the function.

By convention, class names should begin with an upper-case letter.


Name your classes starting with a capital letter.

Here’s another example of a class:

This produces the output:

Name: Alex  Id: 1  Wage: $25
Name: Joe  Id: 2  Wage: $22.25

With normal non-member functions, a function can’t call a function that’s defined “below” it (without a forward declaration):

With member functions, this limitation doesn’t apply:

Member types

In addition to member variables and member functions, classes can have member types or nested types (including type aliases). In the following example, we’re creating a calculator where we can swiftly change the type of number it’s using if we ever need to.



In such a context, the class name effectively acts like a namespace for the nested type. From inside the class, we only need reference number_t. From outside the class, we can access the type via Calculator::number_t.

When we decide that an int no longer fulfills our needs and we want to use a double, we only need to update the type alias, rather than having to replace every occurrence of int with double.

Type alias members make code easier to maintain and can reduce typing. Template classes, which we’ll cover later, often make use of type alias members. You’ve already seen this as std::vector::size_type, where size_type is an alias for an unsigned integer.

Nested types cannot be forward declared. Generally, nested types should only be used when the nested type is used exclusively within that class. Note that since classes are types, it’s possible to nest classes inside other classes -- this is uncommon and is typically only done by advanced programmers.

A note about structs in C++

In C, structs can only hold data, and do not have associated member functions. In C++, after designing classes (using the class keyword), Bjarne Stroustrup spent some amount of time considering whether structs (which were inherited from C) should be granted the ability to have member functions. Upon consideration, he determined that they should, in part to have a unified ruleset for both. So although we wrote the above programs using the class keyword, we could have used the struct keyword instead.

Many developers (including myself) feel this was the incorrect decision to be made, as it can lead to dangerous assumptions. For example, it’s fair to assume a class will clean up after itself (e.g. a class that allocates memory will deallocate it before being destroyed), but it’s not safe to assume a struct will. Consequently, we recommend using the struct keyword for data-only structures, and the class keyword for defining objects that require both data and functions to be bundled together.


Use the struct keyword for data-only structures. Use the class keyword for objects that have both data and functions.

You have already been using classes without knowing it

It turns out that the C++ standard library is full of classes that have been created for your benefit. std::string, std::vector, and std::array are all class types! So when you create an object of any of these types, you’re instantiating a class object. And when you call a function using these objects, you’re calling a member function.


The class keyword lets us create a custom type in C++ that can contain both member variables and member functions. Classes form the basis for Object-oriented programming, and we’ll spend the rest of this chapter and many of the future chapters exploring all they have to offer!

Quiz time

Question #1

a) Create a class called IntPair that holds two integers. This class should have two member variables to hold the integers. You should also create two member functions: one named “set” that will let you assign values to the integers, and one named “print” that will print the values of the variables.

The following main function should execute:

and produce the output:

Pair(1, 1)
Pair(2, 2)

Show Solution

(h/t to reader Pashka2107 for this quiz idea)

b) Why should we use a class for IntPair instead of a struct?

Show Solution

11.3 -- Public vs private access specifiers
11.1 -- Welcome to object-oriented programming

261 comments to 11.2 — Classes and class members

  • kavin

    Hi, i was in lesson 8.5 and found u added an extra example here. Under "Member selection" example line 15,

    why are you doing "member selection with pointer" ? Can't we just write

    because we have direct access to members of the same class right ?

  • Mn3m

  • Luiz

    Hey, in this tutorial at the line which says "Just like a struct declaration, a class declaration does not declare any memory. It only defines what the class looks like." didn't you mean to write "allocate any memory" instead of "declare any memory"?

    These tutorials are awesome by the way.

  • Harmonium nawaz

    I am not able to understand how the class will itself and struct will not, as it was written that both struct and class are unified?? and also an deep explanation of this statement- "it’s fair to assume a class will clean up after itself (e.g. a class that allocates memory will deallocate it before being destroyed), but it’s not safe to assume a struct will."

    • nascardriver

      Both `struct` and `class` can clean up after themselves, they're almost identical.
      By convention, `struct` is used for containers without functionality. You can store data in them, but you're responsible for managing it.
      `class` is used for more advanced types. We could use `class` for storage-only types, but by convention, we write `class`es so that they take care of managing the data.

  • Lord Voldemort

    what are "function parameters"??

  • Lord Voldemort

    in the above code, to print date from the struct, have you changed day variable casually or to make us learn something.

  • Lord Voldemort

    Hey, in the above code, when we're printing date from the struct, why you have prefixed const in argument???

  • Ali

    In the following code from the tutorial, why do you need to pass a reference of the date to the function print? Why not just a copy of the date?

  • Ryder

    Hi everyone:

    I encountered such a code:

    where I cannot find the declaration of `LListBase'

    I just could not find anything like:

    How is this possible? In cpp, every class should have their

  • hero

    Hi, I have a queestion about this line: IntPair p2{ 2, 2 };
    how does the complier know that it needs to access void set?

  • Fernando Rosendo

    Classes are like a blueprint of an object, while an object is an instantiated class. Attributes are characteristics of the to-be-created object(s) while methods are all the actions that the said object(s) will be able to perform.

    Back when I was first learning OOP I had a lot of trouble understanding the basics and that explanation was the one that really made it click, so I suggest that you guys consider adding that to the explanation (if you think it's worthy). Thanks a bunch for the tutorial!

    Here is a bonus example:

  • Nguyen


    "In addition to holding data, classes (and structs) can also contain functions!..."

    I went back to the previous chapters to see if I could find structs that contained functions.  I found none.  Maybe it will be covered later.  I just want to make sure that I did not miss it.  Please let me know.


    • Nguyen

      I just modified the example in the previous chapter that is about structs to see if I could include a function in structs.  It works!

      Here is my modified example.

      • Nguyen

        Since printInformation() is a member function, I don't need to pass the struct itself to the printInformation() function as the first parameter.  The program should look like as shown below:

        Although this works, I'll never try to use structs containing functions.

    • `struct` and `class` is the same thing (Apart from default access), they can be used interchangeable. The only difference is the assumption that `struct` a container without operations on its data, ie. it's used only for storage.
      `class` is assumed to offer functions and operations.

      • Dan

        You give an example that you can't assume the memory allocated for a struct cannot be guaranteed to be deallocated. Would there ever be any reason to risk this, or explicitly resolve issues like this in a program and buck best practice? For example, is there an instance you can think of where a struct would perform better than a class? Or is there simply no benefit from using a struct instead of a class.

        • If all you want to do is store data and don't access it as a whole, use a `struct`.
          Here's an example of a current project of mine. I store the origin and normal of a trace hit (Point where a ray and triangle intersected). I don't want to pass those properties around separately, because that'd make my functions ugly and I always use both properties together.

          All operations on the data are per-member. I don't need to worry about access, construction, or cleanup.

    • Alex

      I don't cover structs containing functions because of the best practice to use the "struct" keyword only for data-only structures. A struct with a function would violate this best practice.

  • mmp52

    Why do we define the class before main function ? Doesn't it have a global scope in that case, which can cause problems if there is a name conflict? Shouldn't it be a static class?


    • Alex

      C++ compiles files in order. IF the class were defined after function main(), the compiler would complain it hadn't see the definition of the class yet when you tried to instantiate an object of the class from inside of main().

      • mmp52

        Thank you for your response.
        But what if I just define the class first, then I will instantiate an object from the class inside the main?

  • Vir1oN

    If you don`t mind pedantic corrections :)

    I feel like there should be a period instead of a colon in the "A note about structs in C++" section, second paragraph, after "assumptions"


    Hello again.
    i change my compiler and download new one and change it's definition to C++17. But still I have the problem. I prefer to remove my zero initialization.
    thanks your advises.


    please help me what kind of adjust settings i have to do?
    I use GNU GCC Compiler with C++11 standard. there is not any changing except to change C++11. it has default setting.
    thanks a lot.


    hi again.
    i found the problem. if i remove my zero initialization value in lines 5-6, problem remove.

    Appreciate your time Nascardriver.


    My Problem is why no default constructor is generated, when i had removed or commented lines 8-14.
    What should i have to do with this compiler message:

    D:\My Documents\C++ Source\Code Blocks\Project 036\main.cpp|
    31|error: no matching function for call to
    31|note: candidates are:
    3|note: constexpr InitPair::InitPair()
    3|note:   candidate expects 0 arguments, 2 provided
    3|note: constexpr InitPair::InitPair(const InitPair&)
    3|note:   candidate expects 1 argument, 2 provided
    3|note: constexpr InitPair::InitPair(InitPair&&)
    3|note:   candidate expects 1 argument, 2 provided

    Maybe I have bad setting Compiler?

    • > Maybe I have bad setting Compiler?
      Yes you do. You've selected the C++11 standard, which doesn't allow aggregate initialization (What you're doing in line 31) when a class member has a default initializer. This restriction was lifted in C++14. Use the newest possible version. (c++2a, c++20, c++17, c++14).


    hello Alex.
    hello Nascardriver.

    I had compile error for "InitPair p2{2, 2};".
    so to solve it i created function "InitPair(int first,int second)".
    Then another error issued by compiler for create "IntPair p1;".
    and again i created "InitPair()" function.

    Realy what is happended? I use CodeBlock. Is it my compiler problem?

    thank you

    • Your code should still compile after removing lines 8-14.
      As soon as you add 1 custom constructor, no default constructor is generated. That's why line 28 doesn't work when you have only the constructor in line 8.

  • Alireza

    I've tried to write struct keyword instead class many times. As I guess there's no difference between class and struct.
    They both have constructor, destructor, can have member function, can have private, public, protected members, etc !
    I can't understand what difference there is !!! I think just keyword's changed.

    • Alex

      The only difference is that classes default members to private, whereas structs default members to public.

      If you always make your access specifiers explicit, there's no functional difference from a language perspective (only from a common use perspective).

  • I want to assign class variables to the function parameters having same names. How can i do this Without using different variable names in the function parameter.

  • Sekhar

    Hi Alex,
    First, when we see an assignment to a variable with the “m_” prefix, we know that we are changing the state of the class.
    Should be modified as:
    First, when we see an assignment to a variable with the “m_” prefix, we know that we are changing the state of the class instance.

  • I'm in love with alex's tutor

    Dear Mr. Alex and Mr.Nas.
      I thank you so much for your kind and great support that enables me to understand the programming world from zero to becoming hero, with a huge motivation and love to code. I always scored grade 'A' in my school as well. ya!!!! This is because of you and only you!!!
       To day i kindly ask you if you have a web tutorial about "data structure and algorithm analysis" or i very kindly ask you to nominate  a good book or website to me. I really sorry since my question is out of the scope of your tutorials.
    I always begging  my lord God to give you peace and lots of blessings!!!

  • Nguyen

    Hi Alex & nascardriver,

    "What do m_year, m_month, and m_day actually refer to? They refer to the associated object (as determined by the caller).

    So when we call “today.print()”, the compiler interprets m_day as today.m_day, m_month as today.m_month, and m_year as today.m_year. If we called “tomorrow.print()”, m_day would refer to tomorrow.m_day instead."

    According to what was written above, I guess when set() is called in quiz 1a, the compiler interprets p1.m_first as m_first and p1.m_second as m_second in the body of the function.  I am wondering if p1.m_first & p2.m_second are destroyed when set() ends?

    Thanks, Have a great day

  • Raga

    I don't really understand why you said that struct having member functions would lead to dangerous assumptions.
    Doesn't the responsibility of cleaning up fall on the struct writer by creating a proper destructor for the struct he made and knows well.
    Certainly the struct user won't have any problems using said struct if he doesn't do anything weird and uncommons right?

    One guidelines I understand better is to use struct when you have no private members / when your variables doesn't have any variances the struct needs to take care of.
    What do you think of that?

    • Alex

      > I don't really understand why you said that struct having member functions would lead to dangerous assumptions.

      By convention, classes are expected to clean up after themselves and ensure any invariants. Structs may or may not depending on whether they're class-like or plain-old-data. This ambiguity opens up room for potential errors, and it's better to just avoid the issue altogether.

      Your proposed guideline is no different than mine -- the term "plain old data" generally means all public members and no invariants. Perhaps I need to do a better job of defining that term.

      • Raga

        > Structs may or may not depending on whether they're class-like or plain-old-data. This ambiguity opens up room for potential errors, and it's better to just avoid the issue altogether.

        Can you give me some examples, I don't really understand how exactly.

        I interpreted your "plain old data" as only having public member variables, because you said you disagreed with the decision to give struct the abilities of having member function. Is that what you mean? The guidelines I talked earlier doesn't really mind though.

        For example, a Vector2D struct has x and y variables, and also might has constructors, dot product function, and maybe override some arithmetic operations. The guidelines permits this struct as all of its variables and functions are public, and modifying the x and y directly won't really break any invariants.

        Maybe some clarifications will help. Thank you so much for your time.

        • Alex

          There are certain guarantees to a "plain old data" (POD) type that no longer apply when you take over construction of a class. Some of these are enumerated here:

          Most of the time, this won't matter, as you probably aren't using most of these capabilities. But at least if we define structs as always being POD types and classes as always being not, then we're less likely to be surprised if/when one things behaves one way and another thing behaves another way because of the difference in POD-ness. PODs also can enable some additional optimizations:

  • lucieon

    can you explain what you mean by "it’s fair to assume a class will clean up after itself, but it’s not safe to assume a struct will."?

    • Alex

      By convention, classes have destructors (functions that execute when the object is destroyed) that will clean up anything that needs to be cleaned up. By "clean up", I mean things like deallocating memory, closing files, disconnecting from networks, etc... Structs may or may not do these things (often not).

  • Hi Alex!

    "classes are very much like data-only structs"
    Shouldn't this be the other way around?
    "structs are very much like data-only classes"

    • Alex

      I see what you're getting at. I've altered the sentence to read, "In C++, classes and structs are essentially the same". Thanks for the feedback.

  • Ryan

    1. How could I improve this?
    2. I tried using vectors instead of dynamic arrays but couldn't get it to work. How would you do this using vectors instead of dynamic arrays

    Any help would be appreciated.

    • Hi Ryan!

      Your code doesn't compile because of lines 20 and 21.
      array[1] doesn't exist. @array has only 1 element.
      There's no point in dynamically allocating @array if you know it's size at compile time.

      Fix these and share your new code so I can change your code to use vectors.

      • Ryan

        Thanks for the help!

  • W

    "For example, it’s fair to assume a class will clean up after itself (e.g. a class that allocates memory will deallocate it before being destroyed), but it’s not safe to assume a struct will."

    Could you please explain further about why it's not safe to assume a struct will clean up after itself? Under my impression, C++ struct also has a default constructor. C++ struct and class are identical apart from the default state of the accesses specifiers.

    • Alex

      Mainly due to the way they are conventionally used. Although structs _can_ clean up after themselves just as well as classes, common usage is to use a struct to move data (no member functions), so typically a struct won't do any cleanup (because that would require a destructor).

      • W

        Thanks for your reply. So if we define a data only struct, there will be no default constructor/destructor when instantiated. If we define a struct with member functions, there will be default constructor/destructor automatically when instantiated. Am I right? How about class If we define a data only class?

        • Alex

          Not quite -- if you define a data only struct or class, it will have a default constructor and destructor that won't do anything.

          Structs are normally used for moving data (and thus don't have any associated functions, even though the compiler may implicitly generate some) whereas classes are treated as complete objects that have setup and cleanup routines.

  • Ryder

    In construction a class

    Should we define all the varibles out of memeber functions?

    I think it is not. Because I can define some varibles in the mumeber functions, and it works.

    My questions, is this a good practice? Or, Should we avoid define varibles within a member function?

    If you can not understand me, please let me know.

    Here I make an example:

    My question is `int m_test = 2;` a bad programming habit?

    • Alex

      In general, there's nothing wrong with using local variables in a member function. Use them just like you would for non-member functions (e.g. when you don't need their values to persist beyond the scope of the function).

      The way you've used it here doesn't make sense though, since print() gets called for each employee, and your "We have 2 employees" statement will get printed twice.

      • Ryder

        Is the following thought a bad programming habit?

        Accessing a local variable in a member function of a class
        from another class.

        For example, I want to access `people` ( in the class 'Employee')
        from another class as shown in the flowing code:

        The class `Boss` is shown in the following code:

        Is that possible to access the local variable ( people.x ) in
        `Employee::print()` from an object of class 'Boss' ? Or, is this
        a bad thought? Is there any other method to achieve this thought?

Leave a Comment

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