Search

Enter your search terms

Submit search form

8.2 — Classes and class members

By Alex on August 30th, 2007 | last modified by Alex on January 27th, 2018

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:

1

2

3

4

5

6

structDateStruct

{

intyear;

intmonth;

intday;

};

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:

1

DateStructtoday{2020,10,14};// use uniform initialization

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:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

#include <iostream>

structDateStruct

{

intyear;

intmonth;

intday;

};

voidprint(DateStruct&date)

{

std::cout<<date.year<<"/"<<date.month<<"/"<<date.day;

}

intmain()

{

DateStructtoday{2020,10,14};// use uniform initialization

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

print(today);

return0;

}

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:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

structDateStruct

{

intyear;

intmonth;

intday;

};

classDateClass

{

public:

intm_year;

intm_month;

intm_day;

};

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:

1

DateClasstoday{2020,10,14};// declare a variable of class DateClass

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. Just like how defining a variable of a built-in type (e.g. int x) allocates memory for that variable, instantiating an object (e.g. DateClass today) allocates memory for that object.

Member Functions

In addition to holding data, classes 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:

1

2

3

4

5

6

7

8

9

10

11

12

classDateClass

{

public:

intm_year;

intm_month;

intm_day;

voidprint()// defines a member function named print()

{

std::cout<<m_year<<"/"<<m_month<<"/"<<m_day;

}

};

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

#include <iostream>

classDateClass

{

public:

intm_year;

intm_month;

intm_day;

voidprint()

{

std::cout<<m_year<<"/"<<m_month<<"/"<<m_day;

}

};

intmain()

{

DateClasstoday{2020,10,14};

today.m_day=16;// use member selection operator to select a member variable of the class

today.print();// use member selection operator to call a member function of the class

return0;

}

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

1

2

3

4

voidprint()// defines a member function named print()

{

std::cout<<m_year<<"/"<<m_month<<"/"<<m_day;

}

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

#include <iostream>

#include <string>

classEmployee

{

public:

std::stringm_name;

intm_id;

doublem_wage;

// Print employee information to the screen

voidprint()

{

std::cout<<"Name: "<<m_name<<

" Id: "<<m_id<<

" Wage: $"<<m_wage<<'\n';

}

};

intmain()

{

// Declare two employees

Employeealex{"Alex",1,25.00};

Employeejoe{"Joe",2,22.25};

// Print out the employee information

alex.print();

joe.print();

return0;

}

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

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

1a) 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.

Share this:

121 comments to 8.2 — Classes and class members

Hi, I didn't understand how initializing classes work, If you add parameters:
MyClass initializationTest {2, 3, 4, "whhhut?"};
It goes on filling variables found in the class matrix in the order you add on the initializer line?
What if you miss some? Or maybe you want to restrict the ability to initialize certain values, how would that work?

1. Create a class IntPair, which holds two public integer variables m_first and m_second. Write a set(int, int) function, which returns void, takes two integer parameters and copy them into m_first and m_second. Also, write a print() function, which prints m_first and m_second to the console.
The following code must compile:

1

2

3

4

5

6

7

intmain()

{

IntPair ip1,ip2{2,2};

ip1.set(1,1);

ip1.print();

ip2.print();

}

...and produce output:

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

Suggested solution:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

#include <iostream>

classIntPair

{

public:

intm_first;

intm_second;

voidset(intfirst,intsecond)

{

m_first=first;

m_second=second;

}

voidprint()

{

std::cout<<"Pair("<<m_first<<","<<m_second<<")";

}

};

intmain()

{

IntPair ip1,ip2{2,2};

ip1.set(1,1);

ip1.print();

ip2.print();

}

2. Whether IntPair should be a class?

Suggested solution:
Since structs are typically used when dealing with data-only structures, class is more suitable here, as IntPair holds functions as well.

Hi vysyaraju!
A struct is usually used for the single purpose of holding data. Whatever happens to that data is up to the coder.
A class is also used to hold data, but it also has functions associated with that data, this includes functions that dynamically allocate and free memory.
When you create a struct and manually allocate memory in it then you're responsible for freeing that memory.
If you have a class then that class will usually allocate that memory on it's own and upon destruction free that memory.

Yes, but it's a bit hard without having covered constructors and destructors yet.

Basically, any well-written class will have a function called a destructor that is executed when the class is destroyed. This destructor function can do any kind of cleanup necessary to return resources to the system (deallocate memory, close a file or database, disconnect from a network, etc...)

Although structs can have destructors, in practice they most often don't (if you want/need to use a destructor, use a class, not a struct). Therefore, if a struct is managing any kind of resource, it's not safe to just assume it will clean up when the struct is destroyed. It may, but it may not.

Dear Mr. Alex!
God bless!!! God Bless!!! God Bless!!!
It is not typing error that i wish God to bless you 3 times! It is a matter of satisfaction about your amazing tutorial among the once i ever seen before. I have discovered many web sites and i have downloaded many books.But only your tutorial gives me a key to get through programing from down the scratch!
I also thank you for my sister to recommend me to read your tutorial. B/s she is able to know who is the best. (she is a post doctoral researcher in computer science in Europe.)
Dear Alex You are helping my country Ethiopia (Africa)through helping me!
I like the way you treated people honestly,for all who share you their difficulties.
God bless!!! God Bless!!! God Bless!!!

Thank you for your answer! I want to ask if after completing this whole websites tutorials I will be able to create a button that you can click on or not... or some kind of cool visual thing. Thank you!

No -- these tutorials don't cover graphical user interfaces, because those are not part of the core C++ language. However, once you have completed these tutorials, you should have enough knowledge to learn a graphical user interface platform (e.g. QT or wxwidgets). Consider these lessons a prerequisite.

Sorry, I am posting a question by clicking reply to some random question.
So please clarify, Structs and classes are same?
Apart from one difference that class can clean up itself, is there no other difference?

hi Alex!!
there are two queries related to this little piece of code
one is , if classes provide opportunity to use data members and methods on a same platform (as being encapsulated) then with structs i can also do the same .. as i used data members declarations and use of functions in structs instead of class and my code is still working ..
second query is that why my compiler that is dev c++ giving me the size of struct 24 ?? and with what respect ??

Yes, in C++ structs and classes are almost identical. However, many people feel it was a bad decision to make structs able to act like classes, so best practice is now to use classes when you have functions, and use structs when you're data-only. This way it's clear whether your object will clean up after itself (class: yes, struct: no).

You're getting a struct size of 24 because that's apparently the sizeof(int) + sizeof(std::string) + sizeof(float), plus any memory used for alignment/padding on your machine.

Hello Alex,
Pls clarify, do we declare variables or define them?
In the following quoted paragraph from above, are the sugested modification of text (or additions), placed in parentheses, correct?
"...In C++, when we define (declare) a variable of a (type corresponding to a defined) class (in short, class type), 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. Just like how defining (declaring) a variable of a built-in type (e.g. int x) allocates memory for that variable, instantiating an object (e.g. DateClass today) allocates memory for that object..."

I was just wondering maybe you know what are the most important diffrences on Xcode and Visual Studio, or maybe you know some site where i can look up to it. This is really important to me so pls answer.

Also, Alex or anyone, I want to practice more programming questions on C++ from basics to advanced(oops). Can anyone share the websites? Preferably, if there are solutions to it, then will be great.
I tried to browse over net but unable to find specifically for C++ that includes control statement, loops, arrays, pointers,strings,oops etc.. questions.