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

  • Hasnat

    How to call a member function of an object to make that member function perform it's task ?
    Plz and

  • durgesh

    Thanks Alex for nice tutorial. I have some doubt in below lines-

    However, there are a few differences. In the struct version of print(), 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 work on.

    Please look at below code-

    Above code is running fine.There is no need to pass struct variable inside function. since we are calling the show() method on "today" object, compiler will automatically call the show() method. from C++ perspective there is no difference between struct and class except default access specifier.

    Please correct me if i am wrong.

    • Alex

      You're not wrong, you're just misunderstanding what I'm trying to say. When I say "In the struct version of print() ...", I was referring to this example:

      In this non-object-oriented context, we have to pass our DateStruct to the function explicitly. In an object-oriented context, that's no longer necessary -- which is exactly the point I'm trying to make.

  • Lyle

    Could you show how to properly break this into .h and .cpp files, and what's required to use it in a main.cpp ?   I've been trying for hours and probably have tried more permutations than are mathematically possible without success.  ( It works fine if I have it in main.cpp, I'm just trying to split into the .h, .cpp and main.cpp style. )
    Thanks -

    • Alex

      Doing this from memory so forgive any small typos:

      ischars.h file:

      .cpp file:

      • Lyle

        Thanks - I was just copying what I got to work to paste here when I saw your response.
        I had to do 2 things though - one was add "bool" in the ischars.cpp before IsChars::operator()(char c)
        and then in the file which contains main, #include "ischar.h"

        It compiles then and works properly. Did what I had to add seem rational ?  
        ( Using gcc 64bit and C:B - where all 3 files were part of the project.)
        Appreciate your time Alex.

  • Fatih

    Hello, I am writing a code in C++ for neuronal networks. Here is a very basic question. How do I assign a uniform random number generator to each neuron and also save the seed number to be able to replicate the simulation if needed?

    For instance, below code produces:
    Last Poisson spike is received at 0 ms
    Last Poisson spike is received at 0.25 ms
    I want to replace 1/rate on line 13 with log(u)/rate where u is from the uniform distribution in (0,1) so neuron would be receiving Poisson-distributed spikes.

    • Alex

      A few thoughts here:
      * You probably don't need each neuron to have their own individual random number generator -- a single generator shared by all members of the class should suffice. So I'd make my random number generator a static member of the Neuron class.
      * The C++ standard library comes with a class to generate uniform distributions:
      * If you want repeatability, then you can just pick a seed (any integer you want) rather than using the default random seed. It looks like the mersenne twister class has a seed() function that you can explicitly call to pass in your own seed:

  • Matt

    Directly above the "Member Functions" section, in the last sentence, you wrote:
    "Instantiating a variable allocates memory for the object". Did you mean to use the word "class" in place of "variable", or is both ways correct?

    • Alex

      It's correct both ways:

      but I think I'll tweak the wording slightly since object usually refers to a class, and not all variables are classes.

  • Sivasankar

    For every lesson, I'm reading and learning something new. Previously I don't have exact answer on "Can a struct contain function (member function) ?". Finally I got the answer here :-). Thank you once again Alex.

  • Hi Alex,
    I am beginner in C++, I just tried to call a class member function using function pointer. but my compiler[Visual studio 2010] throw a syntax error. Can you please help me to sort this issue

    • Alex

      You almost had it.

      • I have one doubt regarding function pointer initialization.
        As per my knowledge from the previous sessions, usually function pointers are initialized through function name,without using the '&' operator. but in class we are using '&' operator to initialize function pointers. Why so?
        is it accessing the function address through claas address?
        Can you please elaborate what it's doing actually

        • Alex

          Non-static member function pointers are really a separable topic from non-member function pointers. The way they work is implemented differently, in part due to the hidden this parameter.

          With normal functions, C++ implicitly converts the function to a pointer as-needed. With member functions, it doesn't, so you have to explicitly include the ampersand.

          • Hi Alex,

            I tried like

            instead of this

            As per your above comment, this also should work, but it's not..

            • Alex

              Where did my comment above imply that using parenthesis should work?

              • sorry for the miss understanding, Form your statements I understood non static member function pointers are not convert in to a pointer, so for getting the address we used ampersand and for accessing the function member function here scope resolution also used.

                This way I understood. May I amwrong.

  • Mauricio Mirabetti

    Alex, another typo, I suppose:
    "...and the class keyword for defining objects ->that that<- require both data and functions to be bundled together."

  • Chris

    Alex, i have question

    at a note about structs in c++ section. What do you mean class will clean it self up, otherwise struct doesn't? may you explain it?
    so this is other difference between them beside the default access specifier?

    Thank you.

    • Alex

      Hey Chris,

      Consider a class that allocates memory. In order not to leak memory, the class should deallocate that memory before it is destroyed. The expectation for classes is that they will do any kind of cleanup necessary (deallocating memory, closing file or database handles, etc...) before they are destroyed, so the program runs in an orderly fashion, even if the class itself is destroyed unexpectedly.

      The only actual difference between a struct in class is in the default access specifier (which we talk about next lesson). The expectation in behavior is just that -- an expectation about best practices, not something the language enforces through syntax.

  • Darren

    Bloomin' Americans!! What kind of logic makes you put a date in this order: month, day, year? It's DAY, month, year!! Grrr....
    Probably something to do with how you pronounce the date. For example May 25, 2007 in American this is May twenty-five, two-thousand-seven. In actual English this is the twenty-fifth of May, two-thousand AND seven. :P (or twenty-o-seven if you're that way inclined)

    Though if you subscribe to any sort of standard date format then use year, month, day (yyyy-mm-dd with your choice of delimiter).

    Anyway rant over. Looking forward to reading the rest of this chapter.

    • Alex

      Yes, I agree, it's silly the way we do it. I've been trying to remember to update all the date formats to yyyy-mm-dd but I missed this article. It's updated now.

  • Jim

    Could you please explain what you mean by this statement or give us a short example. Its just above,
    A note about structs in C++

    "Unlike normal functions, the order in which member functions are defined doesn’t matter!"

    • Alex

      With normal functions, you can't do this:

      Because the call of function add() is above the definition of function add(), the compiler will complain. To fix this, we have to rearrange the code or use a forward declaration.

      However, with member functions, the ordering doesn't matter:

      Even though member function something() is defined after the call to member function something(), that's okay because these are member functions.

  • Leavie

    Hi Alex In example you instantiate object of DateClass using initializer list, this can work, but if i create an empty class constructor, compiler throw error says: "non-aggregate type 'DateClass' cannot be initialized with an initializer list", why this happen? i thought class is upgrade version and compatible with struct before. But they actually be dived two part right?
    thank for your answering.

    • Alex

      Classes with no constructors or private members (or a few other things we haven't covered yet) are a special kind of class called an aggregate. Aggregates are treated like plain old data structs, and can be initialized via an initializer list. However, as soon as you create a constructor, a private member, a virtual function, or any number of other things, the class is no longer an aggregate, and list initialization is no longer allowed. Allowing list initialization on a class with a constructor or private member would allow you to violate the encapsulation of the class, which is not desirable. And thus it is disallowed.

  • naga

    Alex thanks fr the tutorial I's really helping me alot.
    I went through a project , there I saw one class declaration as below

    class VIEWS_EXPORT DeskWiTreeOzone{

    what is VIEWS_EXPORT in that class defination ?

  • Ashish Shankar

    #include <iostream>

    struct DateStruct
        int month;
        int day;
        int year;

    void print(DateStruct &date)
        std::cout << date.month << "/" << << "/" << date.year;

    int main()
        DateStruct today { 10, 14, 2020 }; // use uniform initialization = 16; // use member selection operator to select a member of the struct

        return 0;
    This code will not work out.
    We can't declare the struct object like DateStruct today { 10, 14, 2020 }; // use uniform initialization

  • Jazz

    Alex, I've found out that when std::vector of ClassObjects is resized, Objects are instantiated through the default constructor.

    So, the only way to modify, is to modify every objects througth vector element, after vector has been allocated. Am I right?

  • Jazz


    Is it possible to define a variable of a class (an object) dynamically, in a run-time period?

    For example, I need to fill up the std::vector, by objects based on user-input data.

    Should I use a pointer, instantiated on heap?

    But how to call an appropriate constructor, in this case?

    Sorry for salad from questions, I just want to clarify this situation.

    Thanks in advance!

  • "In C, structs can only hold data, not functions."

    This is incorrect.  In C, a function name is just a pointer to the location of the actual function code.  I wrote a number of LCD display drivers in C driven by a display handler that contained a structure holding information like screen width and height, but also contained functions (or rather the pointers to them) to do things that were hardware-specific.  The code looked something like this:

    In the main driver header file:

    In each display driver C file (this is a global):

    In the main driver C file:

    You can’t place the function in the structure like C++ but I think C++ just puts the pointer to the function in the class and puts the actual code elsewhere.

    This is how you code C++ in C!

  • Aditya

    my college forces me to use turboc++ and hence i have to make some changes to your program. however now it is giving me declaration syntax error when declaring class variable "today".

    On the other hand if i use a getdata function in the class and use cin to get data from user then the program works. I have also tried using semicolons in place of commas while declaring class variable. Any ideas?

    • Alex

      Yep, you're using the uniform initialization syntax here:

      This only works in C++11-enabled compilers, which Turbo C++ is not.

      Since all your members are public, you should be able to use the initializer list syntax:

  • Reaversword

    Hi Alex, two questions about:

    1)I understand perfectly the differences between struct and class, but my question about this is, which are the advantages of an "only data" struct, respect an "only data" class?
    (Because although structs are there, I still would prefer use "only data" class if need it, than a struct. I think i prefer even to forget about structs having classes. Call it sympathy for classes if you want.)

    2)And the most important from my point of view. In lesson 4.7 (structs), you talked us about "data structure alingment" to minimize the total memory a structs occupies. (Well, it was out of the scope of the guide, but there was a mection). Basically, the theory encourages user to order their variables declaration depending of the size of the ones, to declare it in size ascending or descending order.

    So, a words about this in classes? The same rules for data?, and for function declarations what are about?. Some advice?.

    Thanks for your time!

    • Alex

      1) You could write a data-only class, but you really shouldn't. A class should hide its data members, and provide constructors and destructors. Structs (for historical reasons) don't have this association, so they're more appropriate to use when you have the need for a data-only structure. C++ won't stop you from writing data-only classes from a syntax standpoint, but it's not common usage and you'll probably confuse anybody who looks at or tries to use your code.

      2) Both structs and classes use data structure alignment, so there's no inherent savings from using a class over a struct in this regard.

      • Reaversword

        Ok, good point of view, i didn't realized about the usual usage of classes is far more complex than only data structures. Actualy, I'm new with Structs!, so classes are familiar enough to me to think in use only them, but you're undoubtedly right. Thanks one more time.

  • Willy

    When using classes and structs to define an object, is it normal to have all your switch/case statements in your main() such as when a user is presented with a menu and the properties they enter are used to create the object name and its properties from the class or struct?
    Or should a function handle this and if so how?

    • Alex

      It depends on how complicated your program is. If you're doing something simple, you could do it right in main(). If you're doing something more complicated, you'll probably want to create a function to handle it.

  • Joseph

    I've been taught to instantiate classes in other OOP languages like so:

    Does C++ not require you to do this? What happens if you do it this way?

    • Alex

      C++ does not require you to do this.

      will instantiate an object of type MyClass on the stack. This object can be used directly (e.g. myClass.whatever()).

      will instantiate an object of type MyClass on the heap, and return a pointer to that object. This object must be dereferenced before being used (e.g. myClass->whatever()).

      • erad

        Hi Alex,

        You wrote,

        Why are the empty enclosed parentheses needed? Especially seeing that if it were to be for an int or double type, we would have written something as shown below:


  • gans

    Hi Alex,
    Not sure if you still respond to the queries here,
    I'd a query, as I understand, there are no significant differences b/w struct and classes except access specifiers. then Why did we have separate datatype class? we could have use struct in C++.
    Please share your thoughts.

    • Alex

      After designing classes (using the class keyword), Bjarne Stroustrup spent some amount of time considering whether structs (which were inherited from C) should have the same capabilities). After some amount of consideration, he determined that they should, in order to keep the rules simple and have a unified ruleset for both.

      Personally, I feel he made the wrong decision.

      So while technically you can use the struct keyword almost interchangeably with the class keyword for defining objects, in common practice today many programmers use struct to refer to C-style data-only structures, and classes to refer to object-oriented types. This helps reinforce the fact that the fact that they tend to be used differently, and some assumptions that hold true for objects may not hold true for data-only structs (e.g. that they will contain a destructor that cleans up the class after it goes out of scope).

  • Yashar

    I can not understand what is the advantage of "class" relative to "struct".
    It seems they both do the same thing.
    Whether advantage of the class is reduction of defined functions out of the main() ?

    • Alex

      Classes both allow you to bundle the data with the functions that operate on that data, and allow you to specify who can access that data and how (encapsulation). This leads to code that is better organized (as all of the operations that can performed on an object can be accessed through the member selection operator), more modular, and less prone to error.

  • SWEngineer

    Simple well described tutorial.


  • ellankavi

    Hi, I have a question.. Can one class be used to initialize another class? Something like this:

    When I tried to do this, I had some problems in passing parameters to 'class One' from 'class Two'.


    • Biraj Borah

      HI ellanKavi

      Yes u can go ahead and make object of one class in other class ..This is called COMPOSITION ,because the new class is composed of existing class.

      just look the example below to get more info on how to pass parameter

      class One
      private :
      int m_temp ;
      public :
      One(){m_temp = 0;} // this is the default Constructor

      void set(int i) // This the setter of the class
      m_temp = i ;

      class Two

      public :
      One NewOne ; // Embedded Object


      int main ()
      Two objTwo ;
      objTwo.NewOne.set(37); // access the embedded object
      return 0 ;

      You can also go ahead and make a parameterised constructor in the class One and then the value can be passed as a parameter when the class One is instanciated .

      Biraj Borah

  • kruti

    Hi Alex,
    I m not getting the meaning of this line

    "Just like a struct definition, a class definition does not declare any memory."

    please explain it in details.

    • Alex

      only tells the compiler what a DateClass looks like. It does not actually create one. To create one, we need to instantiate the class by defining a variable of that type:

  • srinu

    Hi Alex,
    Why the size of empty Class is one byte?
    Why the size of empty structure is 0 byte?


    • concerned citizen

      Here's some insight to that:

      Basically, if it were size 0 and you made an array out of it, since each array element is 0 in size the entire array would occupy 0 and there would be no way to differentiate say position 0 from position 3

    • Auasp

      empty struct also occupy 1 byte.

  • Prem


    I am a beginner in C++....I have a few doubts/questions regarding the classes programs above..

    In the above program of Today's date, it prints the Today's date, either you declare it directly in (), like (7,31,2009) or you enter it manually using 'cin' for each of the month, date and year.
    But if I want the program to print the Tomorrow's and Yesterday's date by default, after getting the Today's date as input, how could I go for it (using 'class' offcourse)?

    - Prem

    • thejoker585

      simply you will make a function let's name it tomorrowdate and you will add 1 to day and the same to months and years but of course you have to but if conditions to mange this system as there are some months that consists of 30 and others of 31 and another if condition to add 1 to months if day > 31 or 30 you must choose depending on the month no. and so on, i hope i helped u :D

  • Grant

    Hi Alex, Great site!

    My question is, why can't I take the address of a member function through an instance? For example:

    class foo
    void fooFun(){};

    foo x;
    void (*MyfooFun)() = &x.fooFun;

    • Actually, you can, but you have to get the syntax right, and the syntax is so horrid I always have to look it up every time I want to use it.

      • Thanks, Alex, however that syntax does not compile (for me at least). The error message explicitly suggests using


        and not


        if I use


        the error is:

        '&' : illegal operation on bound member function expression

        Anyway, you've shown me how to do it via the class scope syntax and I agree with you that the
        usage is pretty ugly!
        (PS I used the tags but they don't work for me)

        • and

          both seem to work under Visual Studio 6. Microsoft's compilers are sometimes permissive in that they will allow you to do things that aren't officially part of the C++ spec -- I'm not sure if this is one of them.

          Also, I think I fixed the issue with the PRE tags (finally), for future reference.

  • prabhakar

    i have a very fundamental problem.
    a 'class' is declared. it has one 'private data-member' and one 'public member-function'.

    an object (instance of the class) is created after the 'closing curly brackets and the semicolon' of the class-declaration.

    what is the address of the class ?
    what is the address of the class-object ?
    what is the address of the member-function ?

    please enlighten me to keep up my tempo of persuing c++.


    • The class itself does not have an address, because it is just a definition.

      An object of the class does have an address, because it is an actual variable. You can find the address by using the address-of (&) operator:

      Member functions also have an address, because you can set a pointer to them, and you can pass their address into a function:

      ptr is a pointer to a member function of Foo that takes no parameters and returns an integer. It is being set to the address of the Foo::GetValue() function.

Leave a Comment

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