Introduction to Classes in C++

Class in C++

Class in C++

The data types we have applied so far to our variables were used to identify individual items. To create more advanced and complete objects, C++ allows you to group these identifiers and create a newly defined object.

An object, such as a CD Player, a printer, a car, etc, is built from assembling various parts. In the same way, C++ allows you to group various variables and create a new object called a class.

What is a Class?

A class is an organisation of data and functions which operate on them. Data structures are called data members and the functions are called member functions, The combination of data members and member functions constitute a data object or simply an object.

Class in C++

Imagine a company that manufactures shoe boxes hires you to write a program that would help design and identify those shoe boxes. A shoe box is recognized for its dimensions (length, width, height), color, and shoe size that a particular box can contain, etc. The variables that characterize such an object could be:

double Length, Width, Height;
char Color;
float ShoeSize;

A Class Example in C++

class ShoeBox
{
  double Length, Width, Height;
  char Color[12];
  float ShoeSize;
};

The items that compose a class are called members of the class.

And the program that defines a shoe box object could be:

#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
int main()
{
 // Define the characteristics of a shoe box
 // The following characteristics are COMPLETELY random
 double Length(12.55), Width(6.32), Height(8.74);
 string Color("Yellow Stone");
 float ShoeSize = 10.50;

 // Display the characteristics of the shoe box
 cout << "Characteristics of this shoe box";
 cout << setiosflags(ios::fixed) << setprecision(2);
 cout << "\n\tLength = " << Length << "\n\tWidth = " << Width
 << "\n\tHeight = " << Height << "\n\tVolume = " << Length * Width * Height
 << "\n\tColor = " << Color << "\n\tSize = " << ShoeSize << "\n\n";

 return 0;
}

The program would produce:
Characteristics of this shoe box

Length = 12.55
Width = 6.32
Height = 8.74
Volume = 693.22
Color = Yellow Stone
Size = 10.50
Press any key to continue...

Unless dealing with one shoe box, this program would be rudimentary to run for each object. The solution is to create an object called box that groups everything that characterizes the object.

Creating a Class

To create a class, use the class keyword followed by a name for the object. Like any other declared variable, the class declaration ends with a semi-colon. The name of a class follows the rules we have applied so far for variable and function names. To declare a class called ShoeBox, you would type the following:

class ShoeBox;

As a name that represents a group of items, a class has a body that would be used to define the items that compose it. The body of a class starts with an opening curly bracket “{” and ends with a closing one “}”. Therefore, another way to create a class is:

class ClassName{};

This could also be created as:

class ClassName {
};

Either of these techniques produces the same effect.

Since a class is built from combining other identifiers, you will list each variable inside of the body of the class. Each item that composes the class is represented as a complete variable declared with a data type and a name. As a variable, each declaration must end with a semi-colon.

Continuing with our shoe box object, you could create it using the class as follows:

class ShoeBox
{
   double Length, Width, Height;
   char Color[12];
   float ShoeSize;
};

Accessing a Class

A common object in real life is visibly made of two categories of parts: those you can see or touch and those you do not have access to. The parts you can see or touch are considered visible or accessible. In C++, such parts are referred to as public. Those you cannot see or touch are considered hidden. In C++, such parts are referred to as private. Like objects in real life, a class is made of sections that the other functions or other objects cannot ?see? and those the other objects can access. The other objects of of the program are sometimes referred to as the clients of the object. The parts the client of an object can touch in a class are considered public and the others are private.

When creating a class, you will define which items are public and which ones are private. The items that are public are created in a section that starts with the public keyword followed by a semi-colon. The others are in the private section. If you do not specify these sections, all of the members of a class are considered private. For example, all of the members of the previously defined ShoeBox class are private.

Using the public and private sections, our shoe box object can be created as:

class ShoeBox
{
   public:
     double Length, Width, Height;
     string Color;
   private:
     float ShoeSize;
};

The public and private keywords are referenced by their access level because they control how much access a variable allows. You can create as many public sections or as many private sections as you want. For example, the above class could be created as:

class ShoeBox {
  public:
    double Length, Width, Height;
  public:
    string Color;
  double Volume;
  private:
    float ShoeSize;
  private:
    char Material;
  string Color;
};

When creating a class with different public and private sections, all of the declared variables under an access level keyword abide by the rules of that access level. The fact that you use different public sections does not by any means warrant different public levels to the variables. A variable declared as public in one public section has the same public level of access as any other variable that is declared in another public section.

A variable that is declared in a class is called a member of the class. Once the class has been defined, you can use it as an individual variable.

Declaring a Class

After defining a class, you can declare it as a variable using the same syntax we have used for any other variable. A class is declared using its name followed by a name for the defined variable and ending with a semi-colon. For example, our ShoeBox class can be declared as follows:

ShoeBox Shake;

When an object has been declared, you can access any of its members using the member access operator “.”. First, type the name of the object variable, followed by a period, followed by the name of the member you want to access. For example, to access the member Length of the above class, you would write:

Shake.Length;

Using this syntax, you can display the value of a class member:

cout << Shake.Length;

or you can request its value from the user, using the cin operator. Here is an example:

cin >> Shake.Lengh;

Using the

cout

extractor to display the values of the object members, our program could be as follows:

#include <iostream>

#include <string>

using namespace std;

c lass ShoeBox {
    public: double Length,
    Width,
    Height;
    string Color;
    private: float ShoeSize;
};

int main() {
    ShoeBox Shake; // Display the characteristics of the shoe box

    cout << "Characteristics of this shoe box";
    cout << "\n\tLength = " << Shake.Length <<
        "\n\tWidth = " << Shake.Width <<
        "\n\tHeight = " << Shake.Height <<
        "\n\tVolume = " << Shake.Length * Shake.Width * Shake.Height <<
        "\n\tColor = " << Shake.Color <<
        "\n\tSize = " << Shake.ShoeSize <<
        "\n\n";

    return 0;
}

At this time, because of trying to access a private member, the program would produce the following error

[C++ Error] Unit1.cpp(30): E2247 ‘ShoeBox::TShoeSize’ is not accessible

Even if you change the ShoeSize member access from private to public, the program would render unpredictable results because the members have not been given appropriate values:

Characteristics of this shoe box Length = 0 Width = 1.79571e-307 Height = 4.17266e-315 Volume = 0 Color = Size = 3.58732e-43

Press any key to continue…

Techniques of Initializing a Class

There are various techniques used to initialize a class: initializing individual members or initializing the class as a whole.

To initialize a member of a class, access it and assign it an appropriate value.

#include <iostream>

#include <string>

using namespace std;

class ShoeBox {
    public:
        double Length, Width, Height;
    string Color;
    float ShoeSize;
    private:
};

int main() {
    ShoeBox Shake;
    double Volume; // Initializing each member of the class

    Shake.Length = 12.55;
    Shake.Width = 6.32;
    Shake.Height = 8.74;
    Shake.Color = "Yellow Stone";
    Shake.ShoeSize = 10.50;
    Volume = Shake.Length * Shake.Width * Shake.Height;

    // Display the characteristics of the shoe box
    cout << "Characteristics of this shoe box";
    cout << "\n\tLength = " << Shake.Length <<
        "\n\tWidth = " << Shake.Width <<
        "\n\tHeight = " << Shake.Height <<
        "\n\tVolume = " << Volume <<
        "\n\tColor = " << Shake.Color <<
        "\n\tSize = " << Shake.ShoeSize << "\n\n";

    return 0;
}

This time, the program would render a reasonable result.

You can also initialize an object as a variable. This time, type the name of the variable followed by the assignment operator, followed by the desired values of the variables listed between an opening and a closing curly brackets; each value is separated with a comma. The first rule you must keep in mind is that the list of variables must follow the order of the declared members of the class. The second rule you must observe is that none of the members of the class must be another class. In the following example, one of the members of the class is another class, namely a string. Because of the way a variable of the class is declared, the program would not compile:

#include <iostream>
#include <string>

using namespace std;

class ShoeBox {
    public:
        double Length, Width, Height;
    string Color;
    float ShoeSize;
    private:
};

int main() {
    // Declaring and initializing the class as a variable
    ShoeBox LadyShake = {
        12.55,
        6.32,
        8.74,
        "Yellow Stone",
        10.50
    };

    Double Volume = LadyShake.Length * LadyShake.Width * LadyShake.Height;

    // Display the characteristics of the shoe box
    cout << "Characteristics of this shoe box";
    cout << "\n\tLength = " << LadyShake.Length <<
        "\n\tWidth = " << LadyShake.Width <<
        "\n\tHeight = " << LadyShake.Height <<
        "\n\tVolume = " << Volume <<
        "\n\tColor = " << LadyShake.Color <<
        "\n\tSize = " << LadyShake.ShoeSize << "\n\n";

    return 0;
}

Classes and Member Functions

The primary motivation of using classes in a program is to create objects as complete as possible. An object must be able to handle its own business so that the other objects of the program or of another program would only need to know which object can take care of a particular need they have.

A regular variable, as a member of an object, cannot handle assignments; this job is handled by particular functions declared as members of a class. A function as a member of a class is also called a Method. In this book, the words ?method? and ?function?, when associated with a class, will refer to the same thing: a member function of the class.

Declaring Member Functions

A member function is declared like any of the functions we have used so far; it could or could not return a value.

The shoe box we have been using so far needs a volume that would be used to determine what size can fit in the box. Therefore, we will use a member function that can perform that calculation. Our object, when including methods could be structured as follows:

class ShoeBox {
    public:
        double Length;
    double Width;
    double Height;
    string Color;
    float ObtainShoeSize();
    double CalcVolume();
    private:
};

When using functions on a class, the variables are used to hold or store values, called data, of the object, while member functions are used to perform assignments as related to the objects. One way you can control the data held by variables is to hide data from the “external world”. To achieve this, you should declare the member variables in the private section. After doing this, use the methods in the public section to help the class interact with the other objects or functions of the program. At this time, our ShoeBox object would look like this:

class ShoeBox {
    public:
        float ObtainShoeSize();
    double CalcVolume();
    string Color;
    private:
        double Length;
    double Width;
    double Height;
};

There are at least two techniques you can use to implement a method member.

Implementing Member Functions Locally

To implement a method in the class where it is declared, use the same techniques we used to define regular functions. When a method is a class’ member, it has access to the member variables of the same class; this means you do not need to pass the variables as arguments (there are cases when you will need to); you can just use any of them as if it were supplied. Here is how you would define the CalcVolume() method inside of the ShoeBox class:

#include <iostream>
using namespace std;

class ShoeBox
{
public:
float ObtainShoeSize();
double CalcVolume()
{
return (Length * Width * Height);
}
string Color;
private:
double Length;
double Width;
double Height;
};

If your class has a lot of methods, this technique could be cumbersome. You should use it only for small methods.

Implementing Member Functions Globally

When the methods execute long assignments, you should implement them outside of the object by first accessing the desired function member of the class. To access a method of a class when implementing it, instead of the member access operator ?.?, you will use the scope resolution operator represented as two colons ::

To implement a method outside of the class, type the return value of the method, followed by the class’ name, followed by the scope resolution operator ?::?, followed by the method’s name, followed by the arguments, if any, between parentheses, and finally define what the function should do, in its body.

Another implementation of our CalcVolume() method would be:

class ShoeBox <iostream>
{
public:
float ObtainShoeSize();
double CalcVolume();
string Color;
private:
double Length;
double Width;
double Height;
};

double ShoeBox::CalcVolume()
{
    return (Length * Width * Height);
}

Inline Methods

When studying functions, we learned that an assignment can be carried where it is being called. The same process can apply to a class? member.

To declare a class’ method as inline, precede its name with the inline keyword when declaring the method in the class:

class ShoeBox
{
  public:
    inline Double CalcVolume();
    float CalcShoeSize();
    void Display();
   private: . . .
};

You can choose which methods would be inline and which ones would not. When implementing the method, you can precede the method with the inline keyword. You can also omit the inline keyword in the class but use it when defining the method.

If you decide to implement a method locally (in the class), you have the option of implementing it as inline:

class ShoeBox
{
public:
inline double CalcVolume()
{
return Length * Width * Height;
}
inline float CalcShoeSize()
{
return Length - 0.35;
}
void Display();
private:
double Length;
double Width;
double Height;
string Color;
};

On the other hand, if you omit the inline keyword, the C++ compiler would take care of it. Normally, any function implemented in the body of the class is considered inline.

Class Members Interactions

Regardless of how the member methods of an object are implemented, any method can call another without using an access operator. This allows an object?s methods to exchange information among themselves easily. Furthermore, unlike regular functions where a function must be declared prior to another function calling it, the method members of a class do not abide by that rule: one method can call another method before or after the other has been implemented, as long as it is defined somewhere.

#include <iostream>

#include <string>

using namespace std;

class ShoeBox {
    public: ...
};

void ShoeBox::Display() {
    // Initializing the dimensions
    Length = 12.55;
    Width = 6.32;
    Height = 8.74;
    Color = "Early Breeze";

    // Display the characteristics of the shoe box
    cout << "Characteristics of this shoe box";
    cout << "\n\tLength = " << Length <<
        "\n\tWidth = " << Width <<
        "\n\tHeight = " << Height <<
        "\n\tVolume = " << CalcVolume() <<
        "\n\tColor = " << Color <<
        "\n\tSize = " << CalcShoeSize();
}

duble ShoeBox::CalcVolume() {
    return Length * Width * Height;
}

Once an object is defined and behaves as complete as possible, the other function or objects of the program can make the appropriate calls trusting that the called object can handle its assignments efficiently. This ability allows you to (tremendously) reduce the work overload of the other components of a program.

The main() function can simply call the appropriate member of the ShoeBox object now:

int main()
{
ShoeBox Sample;
Sample.Display();

return 0;
}

Tuning Objects

There are other features you can apply to make your objects more professional and less prone to errors. These include constant arguments, constant, private, and inline methods, etc.

Constant Arguments

When studying functions, we learned that when a function receives an argument that it does not modify, the argument should be declared as constant. This allows the compiler to make sure the argument would not be modified. The same technique applies to an argument used by a method of an object.

To declare an argument of an object?s method as constant, type the const keyword on the left of the argument?s data type. To improve our ShoeBox object, we would like to know the area of each side because different things will be displayed on each side and we need to know how much space is available. If we were dealing with a rectangle, we would just declare an Area() method as follows:

 

Double Area();

On a box (rectangular paralleled), we have three rectangles types that represent the six faces.
We can declare one method that takes any two sides and calculates their area. Such a method would be declared as follows:

double Area(Double Side1, Double Side2);

After declaring it in the public section, we would define it as follows:

double ShoeBox::Area(Double Side1, Double Side2)
{
  return Side1 * Side2;
}

In the Display() method, we could display the area of the length by the height using:

cout << ?\n\tArea = ? << Area(Length, Height);

As you can see, the Side1 and Side2 arguments are not modified; therefore, they should be declared as constants. To declare each as constant, we would change the declaration of the method as follows:

Double Area(const Double Side1, const Double Side2);

And we would define it as follows:

double ShoeBox::Area(const Double Side1, const Double Side2)
{
return Side1 * Side2;
}

For an example such as this one, the const keyword can be typed before or after the data type, the result would be the same. If a method is receiving more than one argument, their constancy is independent: the fact that one of them needs to be constant does not imply anything about the other(s).

To help the method specify what side it is calculating the area, we could provide a string that names the side. We could declare the method as follows:

void Area(const Double Side1, const Double Side2, PChar SideName);

We would then define the new method as follows:

void ShoeBox::Area(const Double S1, const Double S2, PChar n)
{
cout << "\nThe area of the " << n << " side is: " << S1 * S2;
}

In the Display() method, we could specify the name of the side and provide the corresponding measures as follows:

Area(Length, Height, "front");Area(Length, Width, "top");Area(Width, Height, "left");

Here is the complete implementation:

#include <iostream>

#include <string>

using namespace std;

class ShoeBox {
    public:
        double CalcVolume() {
            return Length * Width * Height;
        }

    void Area(const double Side1,
        const double Side2, char SideName[]);

    float CalcShoeSize() {
        return Length - 0.35;
    }

    void Display();

    private:
        double Length;
    double Width;
    double Height;
    char Color[32];
};

void ShoeBox::Area(const double S1,
    const double S2, char N[]) {
    cout << "\nThe area of the " << N << " side is: " << S1 * S2;
}

void ShoeBox::Display() {
    // Initializing the dimensions
    Length = 10.42;
    Width = 5.28;
    Height = 5.88;
    Color = "Yellow Stone";

    // Display the characteristics of the shoe box
    cout << "Characteristics of this shoe box";
    cout << "\nDimensions(L*H*W) = " <<
        Length << " * " << Height << " * " << Width;

    Area(Length, Height, "front");
    Area(Length, Width, "top");
    Area(Height, Width, "left");

    cout << "\n\tVolume = " << CalcVolume() <<
        "\n\tColor = " << Color <<
        "\n\tSize = " << CalcShoeSize();
}

int main() {
    ShoeBox Bambou;

    Bambou.Display();

    return 0;
}
Constant Methods

Some of the method members of an object, though using member variables of the same object, do not modify them. To make sure that such a method does not alter the value of a member variable, the method should be declared and implemented as constant.

To declare a method as a constant, add the const keyword to the right side of the method when declaring it. Here is an example:

string SpecFullName() const;

The CalcVolume() and the CalcShoeSize() methods do not modify the member variables they receive. You can reinforce this by declaring them as const:

double CalcVolume() const;float CalcShoeSize() const;

When implementing the method, type the const keyword on the right side of the method?s closing parenthesis:

double ShoeBox::CalcVolume() const
{
return Length * Width * Height;
}

float ShoeBox::CalcShoeSize() const   {   return Length - 0.35; }

If you decide to define constant methods locally (inline), the only difference is to remove the semi-colon of the end of the declaration and define the method normally.

Notice that the Display() method assigns values to the member variables, which means it alters their values. Therefore, it cannot be declared or defined as constant. Here is the new version of our ShoeBox object:

class ShoeBox
{
public:
double CalcVolume() const
{
return Length * Width * Height;
}

void Area(const double Side1, const double Side2, char SideName[]);

float CalcShoeSize() const
{
return Length - 0.35;
}

void Display();

private:
double Length;
double Width;
double Height;
string Color;
};
The program would still produce the same result.

Private Methods

At this time, we know that one of the responsibilities of a member method of an object is to carry assignments. Another job performed by methods is to communicate with the clients of an object. As you might have found out, some of the methods of an object are exclusively used to carry assignments. The external functions or other objects do not call such methods and do not communicate with them. If you create a class and know that a particular member method is not used to transfer data to the client methods, you can declare such a method as private, just like you would do with a member variable.

To declare a method as private, include it in the private section of the object. To implement it, follow the same rules we have learned about implementing the methods of an object. The biggest difference you must keep in mind (which will also be very important when we learn about inheritance) is that this function method is not available to the outside world. Here is an example:

class Employee
{
public:
void IdentifyEmployee();
string FullName() const { return FirstName + " " + LastName; }
void GetHourlySalary();
void CalcTotalHours();
void Display();
void CalcNetPay()
{
if( IsMarried() == false )
NetPay = GrossPay - (GrossPay * 30 / 100);
else
NetPay = GrossPay;
}

private:
void CalcGrossPay();
bool inline IsMarried() const;
string FirstName;
string LastName;
double TotalHours;
double HourlySalary;
double WeeklySalary;
double GrossPay;
double NetPay;
};

Objects and Their Implementations

An object is made of the material that compose it and the actual structure of the object, which defines how the object is built and used. This means, a class is be made of two parts: its building block and its definition. These two parts of a class can be kept in different files that have access to each other.

Class’ Header File

The building block or foundation of an class is made of the class’ creation, listing all of its members. This foundation is created in a file called a header file, similar to the one we learned when studying functions. The name of the file follows the naming rules we have applied so far. The header file has an extension of .h.

You create an object?s header file the same we did when studying functions. To create the header file, you can just define the class as an object. If some of the members are defined in files outsde of the object, include their header file(s).

Here is what our ShoeBox header file would look like

#include <iostream>

#include <string>

using namespace std;

class ShoeBox {
    public:
        double CalcVolume() const {
            return Length * Width * Height;
        }

    void Area(const double Side1,
        const double Side2, char SideName[32]);

    float CalcShoeSize() const {
        return Length - 0.35;
    }
    void Display();

    private:
        double Length;
    double Width;
    double Height;
    string Color;
};

Difference Between Static & Global Variable

Variables defined local to a function disappear at the end of the function scope. So when we call the function again, storage for variables is created andvalues are reinitialized. So if we want the value to be extent throughout the life of a program, we can define the local variable as “static.” Initialization is performed only at the first call and data is retained between func calls.

Had it been goal variable, it would have been available outside the scope of the function, but static variable is not available outside the scope of a function (helpful in localizing errors – as it can’t be changed outside the function
scope).

Static and global variable differ a lot in their behavior to life and scope. First, let me distinguish between life and scope. Life of an object determines whether the object is still in the memory (of the process) whereas scope of the object is whether can I know the variable by its name at this position. It is possible that object is live, but not visible (not in scope) but not that object is not alive but in scope (except for dynamically allocated objects where you refer object through pointers).

Static variables are local in scope to their module in which they are defined, but life is throughout the program. Say for a static variable inside a function cannot be called from outside the function (because it’s not in scope) but is alive and exists in memory. The next time this function is entered (within the same program) the same chunk of memory would be accessed now retaining the
variables old value and no new memory is allocated this time for this variable like other variables in the function (automatic variables). So basically the variable persists throughout the program. Similarly if a static variable is defined in a global space (say at beginning of file) then this variable will be accessible only in this file (file scope).

On the other hand global variables have to be defined globally, persists (life is) throughout the program, scope is also throughout the program. This means such variables can be accessed from any function, any file of the program.

So if you have a global variable and u r distributing ur files as a library and you want others to not access your global variable, you may make it static by just prefixing keyword static (of course if same variable is not required in other files of yours).

M. Saqib: Saqib is Master-level Senior Software Engineer with over 14 years of experience in designing and developing large-scale software and web applications. He has more than eight years experience of leading software development teams. Saqib provides consultancy to develop software systems and web services for Fortune 500 companies. He has hands-on experience in C/C++ Java, JavaScript, PHP and .NET Technologies. Saqib owns and write contents on mycplus.com since 2004.
Related Post