Web LearnCpp

# 8.2 — Classes and class members

While C++ provides a number of basic data types (eg. 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 worked upon. 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:

struct DateStruct
{
int nMonth;
int nDay;
int nYear;
};


Enumerated types and structs represent the traditional non-object-oriented programming world, as they can only hold data. If you want to initialize or manipulate this data, you either have to do so directly, or write functions that take a DateStruct as a parameter:

// Declare a DateStruct variable
DateStruct sToday;

// Initialize it manually
sToday.nMonth = 10;
sToday.nDay = 14;
sToday.nYear = 2020;

// Here is a function to initialize a date
void SetDate(DateStruct &sDate, int nMonth, int nDay, int Year)
{
sDate.nMonth = nMonth;
sDate.nDay = nDay;
sDate.nYear = nYear;
}

// Init our date to the same date using the function
SetDate(sToday, 10, 14, 2020);


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

Classes

In C++, classes are very much like structs, except that classes provide much more power and flexibility. In fact, the following struct and class are effectively identical:

struct DateStruct
{
int nMonth;
int nDay;
int nYear;
};

class Date
{
public:
int m_nMonth;
int m_nDay;
int m_nYear;
};


Note that the only difference is the public: keyword in the class. We will discuss it’s function in the next lesson.

Just like a struct definition, a class definition does not declare any memory. It only defines what the class looks like. In order to use a class, a variable of that class type must be declared:

Date cToday; // declare a variable of class Date

// Assign values to our members using the member selector operator (.)
cToday.m_nMonth = 10;
cToday.m_nDay = 14;
cToday.m_nYear = 2020;


In C++, when we declare 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.

Member Functions

In addition to holding data, classes can also contain functions! Here is our Date class with a function to set the date:

class Date
{
public:
int m_nMonth;
int m_nDay;
int m_nYear;

void SetDate(int nMonth, int nDay, int nYear)
{
m_nMonth = nMonth;
m_nDay = nDay;
m_nYear = nYear;
}
};


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

Date cToday;
cToday.SetDate(10, 14, 2020); // call SetDate() on cToday


Note that in the original struct version of SetDate(), we needed to pass the struct itself to the SetDate() function as the first parameter. Otherwise, SetDate() wouldn’t know what DateStruct we wanted to work on.

However, in our class version of SetDate(), we do not need to pass cToday to SetDate()! Because SetDate() is being called on cToday, the member variables in SetDate() will refer to the member variables of cToday! Thus, inside function SetDate(), m_nDay is actually referring to cToday.m_nDay. If we called cTomorrow.SetDate(), m_nDay inside of SetDate() would refer to cTomorrow.m_nDay.

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.

Here’s another example of a class:

#include <iostream>
class Employee
{
public:
char m_strName[25];
int m_nID;
double m_dWage;

// Set the employee information
void SetInfo(char *strName, int nID, double dWage)
{
strncpy(m_strName, strName, 25);
m_nID = nID;
m_dWage = dWage;
}

// Print employee information to the screen
void Print()
{
using namespace std;
cout << "Name: " << m_strName << "  Id: " <<
m_nID << "  Wage: $" << m_dWage << endl; } }; int main() { // Declare two employees Employee cAlex; cAlex.SetInfo("Alex", 1, 25.00); Employee cJoe; cJoe.SetInfo("Joe", 2, 22.25); // Print out the employee information cAlex.Print(); cJoe.Print(); return 0; }  This produces the output: Name: Alex Id: 1 Wage:$25
Name: Joe  Id: 2  Wage: $22.25  Warning: One of the most common C++ mistakes is to forget to end all class (and struct) declarations with a semicolon. This can cause the compiler to report all sorts of weird, seemingly-unrelated errors!  8.3 — Public vs private access specifiers Index 8.1 — Welcome to object-oriented programming ### 52 comments to 8.2 — Classes and class members • Renu cAlex.Print(); cJoe.Print(); return 0; }; ======> LINE 41 Semicolon in line 41 after } Infact i copy pasted whole code and compiled it and didnt get any error with “}; ” even with semicolon after closing braces.Does compiler ignore that? Thanks, Renu • It’s possible to declare stuff after the end of main() — for example, other variables, functions, etc… The compiler treats that ; as a blank statement, which compiles to nothing. So it’s essentially ignored. There’s no reason for that ; to be there (it was a typo), but it doesn’t hurt either. (As a note to future readers, I removed the extraneous semicolon). • dano I get build errors the on beginning example when trying to initialize manually. struct DateStruct { int nMonth; int nDay; int nYear; }; DateStruct sToday; sToday.nMonth = 10; ---- Errors here. sToday.nDay = 14; sToday.nYear = 2014; void SetDate(DateStruct &sDate, int nMonth, int nDay, int nYear)...  The error is: “expected constructor, destructor, or type conversion before ‘.’ token. Also, not quite sure why the & reference for the &sDate in the SetDate function? Is this so just passing the reference instead of whole structure when calling the function? Thank you for your help. p.s. Love these lessons • Hmm, that’s an odd one. Is the code that uses sToday inside a function, or is it floating in global space? Declarations can be in global space, but code that executes instructions can not be. I would put the following code: DateStruct sToday; sToday.nMonth = 10; sToday.nDay = 14; sToday.nYear = 2014;  inside your main() function and then see if it works. I suspect it will. Also, as far as the & goes, that means we’re passing a DateStruct by reference instead of by value. This will allow SetDate to modify the actual sDate we pass in instead of just a copy. • dano This is the whole thing I’m trying… #include struct DateStruct { int nMonth; int nDay; int nYear; }; int myInt = 5; DateStruct sToday; //sToday.nMonth = 10; *will cause error here //sToday.nDay = 14; //sToday.nYear = 2014; void SetDate(DateStruct &sDate, int nMonth, int nDay, int nYear) { sDate.nMonth = nMonth; sDate.nDay = nDay; sDate.nYear = nYear; } int main() { using namespace std; DateStruct sToday; sToday.nMonth = 10; * works O.K. if I assign here. sToday.nDay = 14; sToday.nYear = 2014; SetDate(sToday, 4, 4, 2008); cout < < "Date values are: " << sToday.nMonth << "/" << sToday.nDay << "/" << sToday.nYear << endl; return(0); }  If I comment out setting the global sToday members and use the ones in main() it works O.K. but not vice versa. So.... you can assign a value to global variables when they are declared but not members of a struct? (int myInt = 5;) Unless I'm making a syntax mistake somewhere. Need grouping braces? {} ? • I see what you are trying to do. Yeah, you can’t assign struct variables in global space that way. If you want to initialize your global struct, you have to do it like this: DateStruct sToday = { 10, 14, 2014 };  • Henk The author doesn’t seem to understand pointers correctly. The usual way to write this code is: void SetDate(DateStruct *sDate, int nMonth, int nDay, int nYear) { sDate->nMonth = nMonth; sDate->nDay = nDay; sDate->nYear = nYear; } And then called it like this: SetDate(&sToday, 4, 4, 2008); The thinking is this. You want something changed. Therefor you need to give the function the address of what needs to be changed. So the input argument must be a pointer. (Hence the *sSDate). When you call the function, you pass it the address of what needs to be changed. • Knight Author has passed struct as a reference and not as an address. Code is correct. • 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: Foo cMyFoo; // declare a Foo object cout < < &cMyFoo << endl; // print its address  Member functions also have an address, because you can set a pointer to them, and you can pass their address into a function: int (Foo::*ptr)() = &Foo::GetValue;  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. • ny hi alex.. still i am confusing about using strncpy.. following line in ur program how its work i still didnt understand strncpy(m_strName, strName, 25); kind regards • strncpy simply copies N character of a zero-terminated string into another string. So the above line copies 25 characters from strName to m_strName. • Alex, But don’t we have to de-reference the strName pointer to copy the value? I noticed that even if we dereference the pointer like below, it gives positive results. strncpy(m_strName, *strName, 25);  Does strncpy() takes care of extracting a string from an address?? or is it something else? Please explain. Regards, Mayur. • [...] 2007 Prev/Next Posts « 7.11 — Namespaces | Home | 8.2 — Classes and class members » Thursday, August 23rd, 2007 at 10:54 [...] • 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. class Foo { public: void Fun() { std::cout << "Fun called" << std::endl; }; }; int main() { Foo pfcnX; // declare a Foo variable void (Foo::*MyFcn)() = pfcnX.Fun; // Set MyFcn to point to pfcnX.Fun (pfcnX.*MyFcn)(); // call MyFcn on pfcnX return 0; }  • 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) • void (Foo::*MyFcn)() = Foo::Fun; // Set MyFcn to point to pfcnX.Fun and void (Foo::*MyFcn)() = &Foo::Fun; // Set MyFcn to point to pfcnX.Fun 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. • frangdara hello everybody I copid the following code and compiled it. It gives the error “Explicit decleration of function ‘int strcpy()’ ”  #include <iostream> class Employee { public: char m_strName[25]; int m_nID; double m_dWage; // Set the employee information void SetInfo(char *strName, int nID, double dWage) { strncpy(m_strName, strName, 25); m_nID = nID; m_dWage = dWage; } // Print employee information to the screen void Print() { using namespace std; cout << "Name: " << m_strName << " Id: " << m_nID << " Wage:$" << m_dWage << endl;
}
};

int main()
{
// Declare two employees
Employee cAlex;
cAlex.SetInfo("Alex", 1, 25.00);

Employee cJoe;
cJoe.SetInfo("Joe", 2, 22.25);

// Print out the employee information
cAlex.Print();
cJoe.Print();

return 0;
}

• M.N. Jayaram

Hi

Which compiler r u using?. I have no problems. I use Code::Blocks studio, the open source cross platform IDE.

• Dayu

To Alex:

Thanks for this excellent tutorial.

I also have some problems with this code. I am using Code::Blocks 8.02. I use GCC compiler.

When I compile it, I have the following error:
…HElloWorld/main.cpp|13|error: ‘strncpy’ was not declared in this scope|

I then add “#include “. Everything works fine except I still get the warning:

…/HElloWorld/main.cpp|31|warning: deprecated conversion from string constant to ‘char*’|

• Jeffrey Rolland

#include <cstring>


to compile with g++ and it will compile. Note that you will still get the warnings, but they are just warnings, not errors; you can ignore the warnings and you will get valid output.

• alex

When you’ll run the class Employee through g++ you’ll get some warnings:

1) You must include the string library because it will not recognise you the strncpy
‘strncpy’ was not declared in this scope

2) You have to put const in front of your char pointer otherwise you’ll receive an warning like below:
deprecated conversion from string constant to ‘char*’

So to solve this warning you have to make like that:

void SetInfo(const char *strName, int nID, double dWage)
{

}

• [...] 2007 Prev/Next Posts « 8.2 — Classes and class members | Home | 8.4 — Access functions and encapsulation » Tuesday, September 4th, 2007 at [...]

• M.N. Jayaram

Superb tutorial!

In the Employee class, I would rather have the statement

using namespace std;

after the #include rather than in the middle of Employee.Print().

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

• K.A.

This section needs rewrite because, apparently, struct is grossly underestimated here and the following code works like a charm:

#include "iostream" // somehow brackets don't display :-)
using namespace std;

struct Date
{
private:
int m_nMonth;
int m_nDay;
int m_nYear;
public:
void SetDate(int nMonth, int nDay, int nYear)
{
m_nMonth = nMonth;
m_nDay = nDay;
m_nYear = nYear;
}
void PrintDate()
{
cout << m_nMonth << " " <<  m_nDay << " " <<  m_nYear << endl;
}
};

int main()
{
Date cToday; // this IS struct  NOT a class
cToday.SetDate(10, 14, 2020); // call SetDate() on cToday
cToday.PrintDate();
return 0;
}


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

• Mahesh

Structs can also hold member functions.

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

•  DateStruct sToday;

// Initialize it manually
sToday.nMonth = 10;
sToday.nDay = 14;
sToday.nYear = 2020;

// Here is a function to initialize a date
void SetDate(DateStruct &sDate, int nMonth, int nDay, int Year)
{
sDate.nMonth = nMonth;
sDate.nDay = nDay;
sDate.nYear = nYear;
}

// Init our date to the same date using the function
SetDate(sToday, 10, 14, 2020); 

Hi Alex, just so you know in this code

 int Year

is supposed to be

 int nYear

Quick question, why do you use DateStruct &sDate in the function instead of just DateStruct sDate (with no ampersand)

• [...] 8.2 Classes and class members [...]

• ellankavi

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

class One
{
....
};

class Two
{
One NewOne;
....
};


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

• hazel reen

Question 2:
Consider the above figure. You can determine the position of a point using the point’s coordinate. Using a class, you need to write a complete C++ program to determine which part a point belongs to based on these :
i. the black area shows that the point is in 1st quadrant
ii. the blue area shows that the point is in 2nd quadrant
iii. the red area shows that the point is in 3rd quadrant and
iv. the green area shows that the point is in 4th quadrant.
If the point is in any part of the y axis, (see the y point), then point is said to be at the x axis. And if the point is at any part of the x axis (see the x point), then it is said to be y axis.
Your program should also provide a constructor function to enables an object to be initializes when it is declared.

• Niranjan

Hi can you explain me the difference between the class declaration and definition , I am bit confused about this .

class example
{
int a ;
public :
fun () { ….}
};

is this is called as a class declaration or definition ?

• SWEngineer

Simple well described tutorial.

Thanks.

• newUser

Wondering if using a class to replace struct is a good idea? And if Mahesh is right, the only different would then be that a class can go private (among other things)!

• dog44wgm

Mahesh IS right.

Alex wrote “In C++, classes are very much like structs, except that classes provide much more power and flexibility”.

But to nitpick, I think he meant to say “In C++, classes and structs are very much like structures in C, except that they provide much more power and flexibility”.

In fact, C++ classes and structs are identical – in the sense that a struct can be/do anything that a class can be/do, and vice versa.

Here is the exhaustive list of differences between a class and a struct:

1. By default, class members are private, struct members are public.
2. By default, classes are inherited privately, structs are inherited publicly.

• [...] which was presented in a C++ Data Structures course. This program was used to practice using the class data structure, which is very similar to the struct data [...]

• [...] in an intro to programming class. This program utilizes a struct, which is very similar to the class concept. For this assignment, the class was asked to make a program which prompted the user to [...]

• [...] in a C++ programming course. This program was assigned to introduce more practice using the class data structure, which is very similar to the struct data [...]

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

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

• anismizi

Dear Alex,
I just copied your code into my codeblocks compiler. But it is showing the following errors.
C:\Users\ANIS\Desktop\C++ practice\text.cpp||In member function ‘void Employee::SetInfo(char*, int, double)’:|
C:\Users\ANIS\Desktop\C++ practice\text.cpp|12|error: ‘strncpy’ was not declared in this scope|
C:\Users\ANIS\Desktop\C++ practice\text.cpp||In function ‘int main()’:|
C:\Users\ANIS\Desktop\C++ practice\text.cpp|30|warning: deprecated conversion from string constant to ‘char*’|
C:\Users\ANIS\Desktop\C++ practice\text.cpp|33|warning: deprecated conversion from string constant to ‘char*’|
||=== Build finished: 1 errors, 2 warnings ===|

• wblakenc

@anismizi,
I hope you figured out the issue with the sample code if not, or possibly to help others confused one thing was left out of the code snip. At the top of the file using ‘strncpy’ you need to include “string.h”. It should show: #include

• pranesh

#include
class Employee
{
public:
char m_strName[25];
int m_nID;
double m_dWage;

// Set the employee information
void SetInfo(char *strName, int nID, double dWage)
{
strncpy(m_strName, strName, 25);
m_nID = nID;
m_dWage = dWage;
}

// Print employee information to the screen
void Print()
{
using namespace std;
cout << "Name: " << m_strName << " Id: " <<
m_nID << " Wage: \$" << m_dWage << endl;
}
};

int main()
{
// Declare two employees
Employee cAlex;
cAlex.SetInfo("Alex", 1, 25.00);

Employee cJoe;
cJoe.SetInfo("Joe", 2, 22.25);

// Print out the employee information
cAlex.Print();
cJoe.Print();

return 0;
}

this is the last example of this chapter. can u tell me why have we used a pointer *strname as a parameter in setinfo function.what if we do not use a pointer?

• [...] WEbsite for programming learning [...]

• CAN I HEARD SOMEONE SAID WEBSITE PROGRAMMING CANT HELP……

THAT MEANS YOU ARE CONFIRMED “ODE”..

I HAVE LEARNT ALOT VIA WEBSITE PROGRAMMING…..

UNLESS YOU DONT NO WAT U AR READING…MAYBE YOUR MIND-SET IS SOME WHERE ELSE…