Search

8.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:

2020/10/16

Classes

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. Using the class keyword defines a new user-defined type called a class.

In C++, classes are very much like data-only structs, except that classes provide much more power and flexibility. 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 declare any memory. It only defines what the class looks like.

Warning: 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.

Just like with a struct, to use a class, a variable of that class type must be declared:

In C++, when we define a variable of a class, we call it instantiating the class. The variable itself is called an instance of the class. A variable of a class type is also called an object. Instantiating a variable allocates memory for the object.

Member Functions

In addition to holding data, classes can also contain functions! Functions defined inside of a class are called member functions. 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:

2020/10/16

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

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.

However, in our class version of print(), we do not need to pass a DateClass to print()! Because print() is being called on class variable “today”, the member variables in print() will refer to the member variables of class variable today! Thus, inside the call to today.print(), m_day is actually referring to today.m_day. If we called tomorrow.print(), m_day inside of print() would refer to tomorrow.m_day.

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. 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.

Rule: 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

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

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 same capabilities. 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, 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 that require both data and functions to be bundled together.

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

Conclusion

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!

8.3 -- Public vs private access specifiers
Index
8.1 -- Welcome to object-oriented programming

48 comments to 8.2 — Classes and class members

  • 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++.

    thanks
    prabhakar.

    • 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.

  • 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(){};
    };

    main()
    {
    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

        &Foo::Fun

        and not

        pfcnX.Fun

        if I use

        &pfcnX.Fun

        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.

  • Prem

    Hello,

    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 😀

  • srinu

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

    Regards,
    Srinu.

    • concerned citizen

      Here’s some insight to that:

      http://bytes.com/topic/c/insights/660463-sizeof-empty-class-structure-1-a

      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.

  • 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:

  • 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’.

    Thanks

    • 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 .

      Regards
      Biraj Borah
      Pune

  • SWEngineer

    Simple well described tutorial.

    Thanks.

  • Yashar

    Hi,
    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.

  • 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).

  • 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()).

  • Willy

    Hi:
    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?
    Thanks,
    Willy

    • 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.

  • 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.

  • Aditya

    Hi
    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:

  • "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!

  • Jazz

    Alex,

    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!

  • 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 objects.properties, is to modify every objects througth vector element, after vector has been allocated. Am I right?

  • Ashish Shankar

    #include <iostream>

    struct DateStruct
    {
        int month;
        int day;
        int year;
    };

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

    int main()
    {
        DateStruct today { 10, 14, 2020 }; // use uniform initialization

        today.day = 16; // use member selection operator to select a member of the struct
        print(today);

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

  • 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 ?

  • 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.

  • Jim

    Alex,
    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.

  • 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. 😛 (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.

Leave a Comment

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

  

  

  

eight + four =