10

Classes

LEARNING OBJECTIVES

At the end of this chapter, you should be able to

  • Write C++ programs using classes and objects.

  • Understand concepts of constructors, destructors, and member data and functions.

  • Understand container classes and their usage.

  • Understand friend functions and inline functions.

  • Understand objects and dynamic memory usage with pointers and reference.

  • Understand this operator and static declarations and their usage.

10.1 Introduction

We use class in C++ to define our own data type. A class is a derived data type like an array. The difference is that in an array you have single data type, while in a class data type you can have different data types. These different data types can be intrinsic data types such as int, float, etc. or derived or user-defined data types or functions or operators.

Object contains data types and functions and/or operators defined by class. So we can call object as an instance of a class. In other words, object is a variable of data type class. We can define an object as an independent entity that holds its own data and member functions. We can say that object tells us the data it holds and allowable operations on the object. A class therefore allows us to encapsulate member functions and member data into single entity called object.

Object-oriented programming involves writing programs that use classes. We create objects of different classes to solve the problem at hand and make objects communicate with each other through the member functions. In this chapter, we will learn how to solve problems by using classes and objects. We will also cover topics such as data hiding and abstraction and access privileges enjoyed by members of the class.

This chapter introduces the concepts of constructor and destructor. Variations in member functions such as friend functions and inline functions are discussed. Classes within a class, called container classes, are introduced. Different methods to use dynamic memory with objects using pointers and references are highlighted with their merits and demerits. This operator and static member functions and their relevance and usage are explained.

10.2 Classes and Objects

Look around your classroom. There are students all around. First of all, why have they been grouped together by your principal? Firstly, because they all share common interests, for example they would like to learn the language C++ or they would like to complete their PG or UG studies. In computer parlance, we can say that all students have the same functionality. That is why they can be grouped together. Figure 10.1 shows member functions and member data.

 

Class member functions and attributes

 

Figure 10.1 Class member functions and attributes

 

But notice that each student has his own individual attributes. Attributes mean own member data like height, weight, marks, attendance, etc. Also notice that there are about 60 students in your class each with his or her own attributes but common functionality. We can call 60 instances of object of Students class. Well so much background for analogy.

Class: A collection of objects. We can also define as an array of instances objects. But class can have member functions and member data. Here, unlike array, a class can have different data types as its elements.

Object: An object is an entity. That is, it can be felt and seen. Examples are student, pen, table, chair, etc. Therefore, an object is an independent entity that has its own member data and member functions.

Data Hiding/Data Abstraction. It is customary to declare all member data as private only. But the data declared as private is hidden and cannot be accessed by any one. This feature is called data hiding or data abstraction. But how can we get them? You can access this only through public member functions. There is no other way. It is comparable to the case where even the chief librarian of a university library cannot take home the books unless he uses the access card supplied by the library.

Public: Member functions and data if any declared as public can be accessed outside the class member functions.

Private: Member data declared as private can only be accessed within the class member functions and data is hidden from outside.

Protected: Member data and member functions declared as protected is private to outsiders and public to descendants of the class in inheritance relationship. You will learn more about this in the chapter on Inheritance.

Encapsulation: Binding together the member functions and member data with access specifiers like private, public, etc. into object by the class is called encapsulation.

Declaring a class: Use keyword class followed by brace brackets. Inside brace brackets we can include member data and member functions as shown below:

 

Example 10.1:   Class Declaration

class Student
{ // constructors and member functions
  public:
      Student(){rollNo=50595,name=”Anand”;}
      ~Student(){}; // Default destructor
      int GetRollNo() const { return rollNo;}
      void SetRollNo ( int n) { rollNo=n;}
  // member data
  private:
      int rollNo;
};

10.2.1 How to Create an Object to a Class?

Remember that an object is a variable of a class. Therefore, you can define the object just like you define a variable of a data type. In the example that follows, we create an ordinary object called std and 50 instances of class Student, as well as a pointer that creates an instance of Student on the Heap memory.

 

Example 10.2:   Creation of an Object of a Class

Student std; // std is an object of class Student
Student std[50]; // There are 50 instances created for Student class
Student *ptr = new Student;// object on free store created

10.2.2 How to Access Member Data and Member Functions?

Once the object to a class is created, we can access the member functions and public member data of a class using dot(.)operator. We have learnt that member data is declared as private in C++ to achieve data hiding and abstraction. Hence, to access these private member data, we need to define public member functions. We call them public accessory functions. To draw an example from our life, you would have observed that books in your library can only be borrowed if you have the library cards. So is the case with the chief librarian; though he is the custodian of the books, he also needs library cards to take books home.

 

Example 10.3:   Accessing Member Functions and Member Data

Student Std: // object is created
Std.SetRollNo(8345); // Sets roll no to 8345
cout<<Std.GetRollNo(); // displays roll number

In our next example, we will show all the concepts we have discussed so far through a class declaration called Polar. In this program, you will learn the concept of class and object, public accessory functions, etc. The class we will consider is vector in Cartesian form denoted by real number a and an imaginary component b. In Polar coordinates, the same can be represented by vector whose magnitude is r given by the formula r = √ ( a2 + b2 ), and the direction is given by θ = tan( b / a ).

Our program will accept the real value a and imaginary component b through a public accessory function called GetData() and convert it to Polar form with magnitude r and angle θ through a public accessory function called ConvertToPolar() and display the result through a function called DisplayPolar(). A word or two about the way we will declare and define functions. If the function to be implemented is big code, then we would declare the prototype inside the class as

 void ConvertToPolar(); // to convert to polar form and define the function code outside the class as shown below:
void Polar::ConvertToPolar()
{ double x=0.0;
  r=sqrt(a*a + b*b);
  x=atan(b/a); // x is in radians
  t= (7.0/22.0)*180.0*x; // conversion to degrees .PI radians 180 degrees
}

Note that we have used the operator :: called scope resolution operator to inform the compiler to link up with function prototype declared within the class. Suppose the function to be implemented is one line or two lines only; we can then declare it as inline function as we have explained in Chapter 3.

    inline double GetMag() const { return r ;}

There is also an easier option of including the code in class definition itself as we have shown: double GetMag() const { return r;}. Then compiler treats the function as inline automatically.

 

Example 10.4:   Polarform.cpp Accessing Member Functions and Data of a Class

#include<iostream>
#include<cmath> // for maths related functions like sqrt,cos, tan, tan- etc.
using namespace std;
// Declaration of class called Polar
class Polar
{  // public accessory functions
   public:
   void GetData();
   double GetReal() const { return a;} // returns real component a. const implies
                                       // function can only return a, but it cannot alter
   double GetImag() const { return b;}
   double GetMag() const { return r;} // Two function GetMag() & GetTheeta
   double GetTheeta() const { return t;} // for Polar form
   void ConvertToPolar(); // to convert to polar form
   void DisplayPolar(); // to display in polar and cartesian forms
// all member data is declared as private
private:
   double r; // magnitude
   double t; // angle theeta
   double a; // real
   double b; // imaginary
};
void Polar::GetData() // :: is called scope resolution operator. It is used since we are
                      // defining GetData() outside the class definition
{  cout<<”Enter Cartesian form Vector Details “<<endl;
   cout<<” Enter real <a> : “;
   cin >>a;
   cout<<” Enter Imaginary <b> : “;
   cin >>b;
   r=0.0; t=0.0;
}
void Polar::DisplayPolar()
{  cout<<"
 Inside the classes member function …"<<endl;
   cout<< "
 Vector in polar form using r and t directly: magnitude = "<<r
   <<" Angle ="<<t<<endl; // We can directly use r and t because it is accessed
                                                                                // inside the member function of the class thus equal to public
   cout<< "
 Vector in polar form using v1.GetMag() etc: magnitude = "<<GetMag()
       <<" Angle ="<<GetTheeta()<<endl;
 }
void Polar::ConvertToPolar()
{  double x=0.0;
   r=sqrt(a*a + b*b);
   x=atan(b/a); // x is in radians
   t= (7.0/22.0)*180.0*x; // conversion to degrees .PI radians equals 180 degrees
}
void main()
{  Polar v1; // v1 is the object of Polar class
   // obtain data for v1
   v1.GetData(); // This is the way we will call member functions using object v1
   // convert to Polar form
   v1.ConvertToPolar();
   cout<<"
 Vectors in Polar form ….
"<<endl;
   v1.DisplayPolar();
   //cout<<"
Vector in polar form : magnitude & Angel = "<<v1.r<<v1.t<<endl;
   //Error ‘r’ ‘t’: cannot access private member declared in class ‘Polar’. Commented out
   cout<<"


 Outside the class using v1.Getmag() etc…."<<endl;
   cout<< "
 Vector in polar form : magnitude = "<<v1.GetMag()
   <<" Angle ="<<v1.GetTheeta()<<endl; // This is the correct way
}// end of
/*Output : Enter Cartesian form Vector Details
Enter real <a> : 3
Enter Imaginary <b> : 4
Vectors in Polar form form ….
Inside the class …
Vector in polar form using r and t directly: magnitude = 5 Angle =53.1087
Vector in polar form using v1.GetMag() etc: magnitude = 5 Angle =53.1087
Outside the class using v1.Getmag() etc….
Vector in polar form: magnitude = 5 Angle =53.1087
*/

A few points to remember

Inside member functions that is invoked by object you can access the private members directly. For example, in function DisplayPolar(), we have used cout<<r. This is ok.

But outside, like in main, we cannot use v1. r. We have to use public accessory function like v1.GetMag().

10.2.3 Constructors and Destructors

When you need to construct a house, you go to a specialist called architect or mason so that they make the house ready for occupation and usage. So is the case with Class. When a class is declared and an object is created, the constructor for the class is called. His job is to create the object, allocate memory for the data members and initialize them with initial values if supplied by the user.

The constructor will have the same name as that of the class but no return value. The constructor needs to be declared as public.

Student(){ } // Default constructor. No initial values. If you do not declare the default constructor, compiler automatically creates it. Hence, the term default constructor.

Overloading means the same function name but different types or different numbers of arguments. For example:

  Student ( int n, char * p) { rollNo=n, name = p ; } is an overloaded constructor.

Destructor: When the program has ended there is a need to clear the memory resources allocated to it. This job is done by the destructor.

~Student(){ }; // Default destructor. The default destructor is called automatically when the program ends.

Copy Constructor: This is the second of the special constructors, the first being default constructor, created automatically, if you do not create on your own. It takes one argument i.e., the object to be copied. Look at the following declaration and definition:

Student( const Student & src) :rollNo(src.rollNo),name(src.name){}

The object is passed as constant reference so that it cannot be altered. Once declared, we can use it to copy the entire state of the object into new object.

Student std; // object is created
Student std1(std) ; // entire object std is copied on to std1

Let us attempt a problem to make our understanding of constructors and destructors clearer. In this program, you will learn the concept of class constructor overloaded constructor, copy constructor, default destructor, etc.

 

Example 10.5:   classbasic2.cpp Constructors and Destructors of a Class

#include<iostream>
using namespace std;
//declare a class called Student
class Student
 {   public:
     // overloaded constructors
     Student(){rollNo=0,name=”No Name”;}
     Student(int n, char *p){rollNo=n,name=p;}
     Student( const Student & src) // copy constructor
     { rollNo=src.GetRollNo();name=src.GetName();
         cout<<” Copy Constructor….”<<endl;}
     ~Student(){}; // Default destructor
     // public access functions
     int GetRollNo() const { return rollNo;}
     void SetRollNo ( int n) { rollNo=n;}
     char * GetName() const { return name;}
     void SetName( char *p) { name=p;}
private:
int rollNo;
      char *name; // pointer to name
};
 void main()
 { Student std; // object created
      cout<<” 
 Students rollNo set by Default constructor : “
         <<std.GetRollNo()<<endl;
      cout<<”
 Students name set by Default constructor : “
         <<std.GetName()<<endl;
   //set roll no to 6060 and name to gautam.
   //We have to use public accessory function to update private data
   // Why ? Because we are not inside member function
   std.SetRollNo(6060);
   std.SetName(“Gautam”);
      cout<<”
 Students rollNo set by SetRollNo :”
         <<std.GetRollNo()<<endl;
      cout<<”
 Students name set by SetName :”
         <<std.GetName()<<endl;
   // Now let us make use of overloaded constructor
   Student std2(7070,”Ramesh”);
   cout<<” 
 Students rollNo set by (int n, char *p) overloaded 
   constructor : “
        <<std2.GetRollNo()<<endl;
   cout<<”
 Students name set by (int n, char *p) overloaded : “
       <<std2.GetName()<<endl;
   // Now let us use copy constructor and copy std2 onto std3
   Student std3(std2); // std is copied on to new object called std3
   cout<<” 
 Students(std3 rollNo) : “<<std3.GetRollNo()<<endl;
   cout<<”
 Students (std3 name) : “<<std3.GetName()<<endl;
}
/*Output : Students rollNo set by Default constructor : 0
Students name set by Default constructor : No Name
Students rollNo set by SetRollNo :6060
Students name set by SetName :Gautam
Student(std2.rollNo) set by (int n, char *p) overloaded constructor : 7070
Student(std2.name) name set by (int n, char *p) overloaded : Ramesh
Copy Constructors
Students(std3 rollNo) : 7070
Students (std3 name) : Ramesh*/

We have explained the salient features in the running program itself. Also take a final look at the public accessory functions we have used.

int GetRollNo() const { return rollNo;}
char * GetName() const { return name;}

When we do not want the function to alter value, we declare as constant as shown above. It will be an error if we write int GetRollNo() const { return rollNo++;}. Whereas in the functions shown below SetName can set, i.e. alter the name. Hence we have not declared as constant.

void SetName( char *p) { name=p;}
void SetRollNo ( int n) { rollNo=n;}

Look at the constructor declaration and definition we have declared and defined as

Student(int n, char *p){rollNo=n,name=p;} .

We can also declare and define it as

Student(int n, char *p) : rollNo(n), name(p) { } . We will be using this mode of declaration and definition in all our programs henceforth.

10.3 Friend Function

Due to data encapsulation and data hiding features of C++, only public member functions can access private data. We can also declare member functions to access private data, like we have been using GetData() in our programs, but it is cumbersome. Is there a method by which we be can access private data through a non-member function? Friend operator just achieves that. You can include a non-member inside a class by declaring it as friend.

For example, let us revisit the Polar class, declare friend functions for Multiplication and DisplayData() and see ourselves how the program gets simplified.

friend void DisplayPolar(Polar v); // to display in polar forms
friend Polar Multiply(Polar v1, Polar v2);

When defining these friend functions outside the class, there is no need to use scope resolution operator:: since friend functions are non-members.

void DisplayPolar(Polar v) // For a friend we do not use scope resolution operator
{// We can directly use r and t because DisplayPolar() is a friend function
  cout<<”Magnitude”<<v.r<<” Angle =”<<v.t<<endl;
}
Polar Multiply(Polar v1, Polar v2)
{     Polar v3;
      v3.r = v1.r * v2.r; // multiply the magnitudes
      v3.t = v1.t+v2.t; // add the angles
      return v3;
}

Also notice that though the functions are non-members, because they are friend functions we could use private data directly without using public accessory functions. What is then the cost paid for this simplification? You have given access to private data to a non-member function.

 

Example 10.6:   classbasic3.cpp Friend Functions of a Class

/* In this program, you will learn the concept friend operator.
Two functions Multiply and DisplayData are declared as friend functions*/
#include<iostream>
#include<cmath> // for maths related functions like sqrt,cos, tan, tan- etc
using namespace std;
// Declaration of class called Polar
class Polar
 { //public accessory functions
     public:
     Polar():r(0.0),t(0.0){} // Default constructor
     Polar( double f, double g):r(f),t(g){} // This is how we will declare
                                                 // constructor
     ~Polar(){} // Default Destructor
     friend void DisplayPolar(Polar v); // to display in polar forms
     friend Polar Multiply(Polar v1, Polar v2);
     // all member data is declared as private
     private:
       double r; // magnitude
       double t; // angle theeta
};
void DisplayPolar(Polar v) // For a friend we do not use scope resolution operator
{ // We can directly use r and t because DisplayPolar() is a friend function
 cout<<”Magnitude”<<v.r<<” Angle =”<<v.t<<endl;
}
Polar Multiply(Polar v1, Polar v2)
{     Polar v3;
      v3.r = v1.r * v2.r; // multiply the magnitudes
      v3.t = v1.t+v2.t; // add the angles
      return v3;
}
void main()
{Polar v1(5.0,53.0),v2(6.0,28.0),v3; // v1,v2,v3 is the object of Polar class
// multiply Polar Vectors v1 & v2 and store it in v3
   v3=Multiply(v1,v2);
   cout<<“
The Given Vectors in Polar form form ….
“<<endl;
   cout<<“
Polar form vector v1 :“;
   DisplayPolar(v1);
   cout<<“
Polar form vector 2 v2 :“;
   DisplayPolar(v2);
   cout<<“
v3=v1*v2 in Polar Form :“;
   DisplayPolar(v3);
}// end of main
/*Output :The Given Vectors in Polar form form ….
Polar form vector v1 :Magnitude5 Angle =53
Polar form vector 2 v2 :Magnitude6 Angle =28
v3=v1*v2 in Polar Form :Magnitude30 Angle =81*/

10.4 Class Within a Class: Container Class

Container class is one of the techniques provided by C++ to achieve reusability of the code. Inheritance is another powerful feature for reusability which we will explore in the chapter on inheritance.

Container class means a class containing another class or more than one class. For example, a computer has a microprocessor in it. Further, a Student class can have a data member belonging to a string class. Then we would say that the string class is contained in the Student class. In other words, it can also be called composition or aggregation of string class. The advantage of containment is that we can use string class within Student class to store the details of name and address, etc., belonging to string class. Similarly, if we define a class called Date with day, month and year information, we can define object of Date within a class called Student and define Date-related data such as DOB, DOJ, etc.

Composition is a “has”-type of relation. For the example we have given above Student has name of string class and DOB of Date class.

 

Example 10.7:   PointCircle.cpp An Example for Container Class, i.e. Class as a Data Member of Another Class. Constructors and Destructors of a Class

In this program, you will learn the concept of class within a class. That is, class as a data member of another class. We will define a class called Point and later declare this as a data member of class called Circle. We will then find the area of the circle.

#include<iostream>
#include<cmath>
using namespace std;
// Declare a class called Point
class Point
{     public:
      Point(){} // default constructor
      ~Point(){} // default Destructor
      float GetX() const { return x;}
      void SetX(float f) { x=f;}
      float GetY() const { return y;}
      void SetY(float f) { y=f;}
private:
      float x;
      float y;
};
class Circle
{ // We will use user defined data called Point declared above
 public:
      Circle(float r, float p, float q );
      ~Circle(){} // default Destructor
      Point GetCircleCenter() const { return CircleCenter;}
      void SetCircleCenter(Point f) { CircleCenter=f;}
      float GetCircleRadius() const { return CircleRadius;}
      void SetCircleRadius(float f) { CircleRadius=f;}
      float GetArea() const; // Fn to Find Area of the Circle
 private:
      float CircleRadius;
      Point CircleCenter; // CircleCenter is a object of class Point
};
Circle::Circle(float r, float p, float q)
{
      CircleCenter.SetX(p); // CircleCenter is object of Point 
      class
      CircleCenter.SetY(q);
      CircleRadius=r;
}
float Circle::GetArea() const{return (22.0/7.0)*CircleRadius*CircleRadius;}
void main()
{ Circle circ(3.0,1.5,2.5); // object is created with center(1.5,2.5) 
  and Radius=3.0
  float area=circ.GetArea();
  cout<<” area of the circle with radius = “<<circ.GetCircleRadius()
  <<” Center(“<<circ.GetCircleCenter().GetX()
  <<”,”<<circ.GetCircleCenter().GetY()<<”)=”<<area<<” Sq Units”<<endl;
}/*Output:
area of the circle with radius = 3 Center(1.5,2.5)=28.2857 Sq Units*/

Observe the cout statement we have used circ.GetCircleCenter() returns a Point data type. With this Point we have invoked GetX() and GetY().

  cout<<” area of the circle with radius = “<<circ.GetCircleRadius()
  <<” Center(“<<circ.GetCircleCenter().GetX()
  <<”,”<<circ.GetCircleCenter().GetY()<<”)=”<<area<<” Sq Units”<<endl;

As another example consider a class called Student containing another class called Date.

Date class has date information as data members and public accessory function to set and get date fields such as day, month and year. Class Student declares variables belonging to class Date as shown below:

  Date dateDOB;
       Date dateDOJ;

Member functions to access these private variables are also declared. It may be noted that GetDOB() returns variable of type Date.

 Date GetDOB() const { return dateDOB;}
 Date GetDOJ() const { return dateDOJ;}
 void SetDOB( Date dtb) { dateDOB=dtb;}
 void SetDOJ( Date dtj) { dateDOJ=dtj;}

 

Example 10.8:   DateStudent.cpp Student Class Contains Date Class. Constructors and Destructors of a Class

#include <iostream>
using namespace std;
class Date
{public:
 Date ( int d=0, int m=0,int y=0) :dd(d),mm(m),yy(y) { } // constructor
 void SetDate( int d, int m, int y){ dd=d,mm=m,yy=y;}
 int GetDD() const { return dd;};
 int GetMM() const { return mm;};
 int GetYY() const { return yy;};
 private:
      int dd;
      int mm;
      int yy;
};
class Student
{ public:
    Student();
    ~Student(){}; // Default destructor
    int GetRollNo() const { return rollNo;}
    void SetRollNo ( int n) { rollNo=n;}
    Date GetDOB() const { return dateDOB;}
    Date GetDOJ() const { return dateDOJ;}
    void SetDOB( Date dtb) { dateDOB=dtb;}
    void SetDOJ( Date dtj) { dateDOJ=dtj;}
 private:
    int rollNo;
    Date dateDOB;
    Date dateDOJ;
};
Student::Student()
{ dateDOB.SetDate(14,11,54);
  dateDOJ.SetDate(25,11,77);
  rollNo=5050;
}
void main()
{ Student std; // object created
  cout<<” 
 Students rollNo set by Default constructor : “<<std. GetRollNo()<<endl;
   cout<<”
 date of Birth :”;
   cout<<std.GetDOB().GetDD()<<”/”<<std.GetDOB().GetMM()
  <<”/”<<std.GetDOB().GetYY()<<endl;
   cout<<”
 date of Joining :”;
   cout<<std.GetDOJ().GetDD()<<”/”<<std.GetDOJ().GetMM()
  <<”/”<<std.GetDOJ().GetYY()<<endl;
}
/*Output : Students rollNo set by Default constructor : 5050
date of Birth :14/11/54
date of Joining : 25/11/77*/

Note that in cout statements in the main program, std.GetDOJ() returns data type of Date. Hence, with that variable we have further invoked GetMM().

10.5 Objects and Data Members on Heap Memory

We have learnt that Heap memory is dynamic memory and we can derive lot of advantage by using heap memory. The main advantage is the conservation of primary memory that arises as a result when we load objects, use and free the memory after use. In this way we can solve large complex problems. So naturally we have to equip ourselves with the skills for deploying objects onto heap memory. As an example, we can declare a class called Student. We can further declare a pointer to that class and create an object of Student on Heap Memory.

    Student *ptr - new Student;// object on free store created

We use in direction operator -> to access the object functions and member data on the heap. : cout<<ptr->GetName()<<endl; // access member data from heap. After use we need to free the heap memory allocated. :delete ptr; // we need to delete and free dynamic memory. The following program makes things clear.

 

Example 10.9:   objheap.cpp Creation of Object on to Heap Memory and Access Member Data. Constructors and Destructors of a Class

#include<iostream>
using namespace std;
//declare a class called Student
class Student
 {public:
       Student(){rollNo=50595,name=”Anand”;}
 ~Student(){}; // Default destructor
       int GetRollNo() const { return rollNo;}
       void SetRollNo ( int n) { rollNo=n;}
       char * GetName() const { return name;}
       void SetName( char *p) { name=p;}
private:
       int rollNo;
       char *name;
};

void main()
{ Student std; // object created
     Student *ptr = new Student;// object on free store created
     cout<<” 
 Students rollNo set by Default constructor : “
      <<ptr->GetRollNo()<<endl;
     cout<<”
 Students name set by Default constructor : “
      <<ptr->GetName()<<endl; // access member data from heap
     //set roll no to 50
     ptr->SetRollNo(6060);
     ptr->SetName(“Gautam”);
     cout<<”
 Students rollNo set by SetRollNo :”
      <<ptr->GetRollNo()<<endl;
     cout<<”
 Students name set by Default constructor :”
      <<ptr->GetName()<<endl;
     //now delete the memory from heap
     delete ptr; // we need to delete and free dynamic memory
 }
/*output :Students rollNo set by Default constructor : 50595
Students name set by Default constructor : Anand
Students rollNo set by SetRollNo :6060
Students name set by Default constructor :Gautam*/

In the above example, we have created entire object on heap memory. We can also create the member data on heap memory and use indirection operator -> to access data members. Note that heap memory can be accessed only through the use of pointers. Therefore, our declaration of member data would be pointers

int *rollNo; // we have to use pointers as we want to use Heap Memory
char *name;

Our public accessory functions have to deal in pointers :

int GetRollNo() const { return *rollNo;}

Creation of object onto heap memory and access of members would be

Student *ptr = new Student;// object on heap created
cout<<ptr->GetRollNo()<<endl;

 

Example 10.10:   objmemheap.cpp Creation of Object and Member Data on to Heap Memory and Access Member Data Using Indirection Operator -> Member Data. Constructors and Destructors of a Class

#include<iostream>
using namespace std;
//declare a class called Student
class Student
{ public:
     Student();
     ~Student(){delete rollNo;delete name;} // Default destructor
     int GetRollNo() const { return *rollNo;}
     void SetRollNo ( int n) { *rollNo=n;}
     char * GetName() const { return name;}
     void SetName( char *p) { name=p;}
private:
     int *rollNo; // we have to use pointers as we want to use Heap Memory
     char *name;
};
     Student::Student(){rollNo= new int(50);name= new char;name=”ramesh”;}
void main()
{ Student *ptr = new Student;// object on heap created
   cout<<” 
 Students rollNo set by Default constructor : “
         <<ptr->GetRollNo()<<endl;
   cout<<”
 Students name set by Default constructor : “
         <<ptr->GetName()<<endl;
         //set roll no to 6060
         ptr->SetRollNo(6060);
         ptr->SetName(“Gautam”);
   cout<<”
 Students rollNo set by SetRollNo :”
         <<ptr->GetRollNo()<<endl;
   cout<<”
 Students name set by Default constructor :”
         <<ptr->GetName()<<endl;
}//end of main
/*Output : Students rollNo set by Default constructor : 50
Students name set by Default constructor : ramesh
Students rollNo set by SetRollNo :6060
Students name set by Default constructor :Gautam*/

10.6 This Pointer

We are aware that memory management of C++ allocates separate memory area called code section for your code. Accordingly your function code will be in this area. But we also know that variables are stored either in stack area or in heap memory. When a function is invoked by an object, there is a need to link up function that is called with the objects data. Therefore, the object is forwarded to function as an argument to that function. But this argument, i.e. address of the object invoking the function, is not visible like ordinary formal arguments and it is hidden. This hidden address is called this pointer. It is called this because it points this object, i.e. object that has invoked the function.

In a function if you use this pointer explicitly then it refers to object member data. Note that we can get the same effect by using object instead. But note that this is a pointer and hence it has all the advantages of instant and fast access to object. Look at the program at Example 10.9 rewritten using this pointer.

 

Example 10.11:   this.cpp Object on to Heap Memory Using this Pointer. Constructors and Destructors of a Class

#include<iostream>
using namespace std;
class Student
{ public:
     Student(){rollNo=50595,name=”Anand”;}
     ~Student(){}; // Default destructor
     int GetRollNo() const { return this->rollNo;}
     void SetRollNo ( int n) { this->rollNo=n;}
     char * GetName() const { return this->name;}
     void SetName( char *p) { this->name=p;}
private:
     int rollNo;
     char *name;
};
void main()
{    Student std; // object created
     Student *ptr = new Student;// object on free store created
     cout<<” 
 Students rollNo set by Default constructor : “
           <<ptr->GetRollNo()<<endl;
     cout<<”
 Students name set by Default constructor : “
           <<ptr->GetName()<<endl; // access member data from heap
     //set roll no to 50
     ptr->SetRollNo(6060);
     ptr->SetName(“Gautam”);
     cout<<”
 Students rollNo set by SetRollNo :”
           <<ptr->GetRollNo()<<endl;
     cout<<”
 Students name set by Default constructor :”
           <<ptr->GetName()<<endl;
     //now delete the memory from heap
     delete ptr;
}
/*Output :Students rollNo set by Default constructor : 50595
Students name set by Default constructor : Anand
Students rollNo set by SetRollNo :6060
Students name set by Default constructor :Gautam*/

10.7 Pointers vs Objects: Use of Constant Declarations

We are aware that pointers are addresses and provide us a fast access to memory and data manipulation. But there are issues of safe operation and data integrity. In Section 4.5.11, we have seen the use of pointers and effect of declaration of const pointer and constant data. In this section, we will study the effect and efficacy of using const declaration to pointers while working with objects. While manipulating objects stored in memory, a programmer faces several demanding situations such as data should not be altered. In such cases, we would have declared that data as constant.

The pointers to be constant i.e. they should not be reassigned. In such cases, we would declare as const pointers.

Thus, there are two combinations involved, i.e. Pointer type and Data Type. Each type can have two variations of data type: constant and normal. Therefore, we can have a total of four variations in declaration of variables. These are shown below:

Pointer to Object
// normal pointer & Normal object on heap
Student *ptr = new Student; // ptr is normal pointer on heap
Pointer to const Object
// conststudent is a pointer to constant Student
const Student *conststudent = new Student;
Const pointer to Object
//constptr is constant pointer to Student
Student * const constptr = new Student;
Const pointer to a const Object
//cptrcstd is a constant pointer to constant student
Const Student * const cptrstd = new Student;

In the example that follows we would demonstrate the methods and rules for deployment of different types of pointers and data type discussed above. When we use normal pointer to normal objects on heap, we can use Get() and Set() functions. Usage of Set() function implies that we can modify the objects data. Note that all Get () functions we would have declared Get() as const. so that it cannot alter the data values but it can only browse these values

Student *ptr = new Student;
int GetRollNo() const { return rollNo;} // only read . Function cannot alter data.
void SetGrade( char p) { grade=p;}

When we use pointer to constant object, we cannot use serGrade() functions as it sets data for grade. This is so because we have declared the object as constant.

// conststudent is a pointer to constant Student
const Student *conststudent = new Student;
ptr->SetGrade(‘C’); // NOT OK

When we use the third option, i.e. const pointer to constant object, pointer cannot be reassigned nor can the data be amended.

// const pointer to constant object
Const Student * const cptrstd = new Student;
int GetRollNo() const { return rollNo;} // Allowed
ptr->SetGrade(‘C’); // NOT OK

 

Example 10.12:   ptrcdata.cpp To Demonstrate Use of Constant Pointer and Constant Object. Constructors and Destructors of a Class

#include<iostream>
using namespace std;
//declare a class called Student
class Student
{ public:
     Student(){rollNo=50595,grade=’A’;}
     ~Student(){}; // Default destructor
     int GetRollNo() const { return rollNo;}
     void SetRollNo ( int n) { rollNo=n;}
     char GetGrade() const { return grade;}
     void SetGrade( char p) { grade=p;}
private:
     int rollNo;
     char grade;
};
void main()
     { // ptr is normal pointer on heap
     Student *ptr = new Student;
     // conststudent is a pointer to constant Student
     const Student *conststudent = new Student
     //constptr is constant pointer to Student
     Student * const constptr = new Student;
     const Student * const cptr = new Student;
     cout<<”explore the possibilities with normal heap pointer *ptr”<<endl;
     cout<<” 
 Students rollNo set by Default constructor : “
           <<ptr->GetRollNo()<<endl;
     cout<<”
 Students Grade set by Default constructor : “
           <<ptr->GetGrade()<<endl;
     //set roll no to 50 and Garde to B
           ptr->SetRollNo(6060);
           ptr->SetGrade(‘B’);
     cout<<“
 Students rollNo set by SetRollNo() function :“
           <<ptr->GetRollNo()<<endl;
     cout<<“
 Students name set by setgrade() function:“
           <<ptr->GetGrade()<<endl;
     cout<<“
explore the possibilities with pointer *conststudentto“<<endl;
     cout<<“ constant object Student“<<endl;
     cout << ”
 Display Grade …“<<conststudent ->GetGrade()<<endl;
     //conststudent->SetGrade(‘C’); //NOT OK.
     /*const pointer calling non-const fn . This is error. conststudent is a pointer to constant Student, whereas SetGrade is a non-constant function and can change value. Hence we cannot use. You will observe error C2662: ‘SetGrade’ : cannot convert ‘this‘ pointer from ‘const class Student‘ to ‘class Student &‘ Hence it
 shown in comments */
     // constant pointer to constant data object
     cout<<“
explore the possibilities with const pointer *cptr to“<<endl;
     cout<<“ constant object Student“<<endl;
     cout<<“
cptr-> GetGrade()..“<<cptr->GetGrade()<<endl;//ok
     //cout<<“
cptr->SetGrade(‘C‘)..“<<cptr->SetGrade(‘C‘)<<endl;//not ok
     //now delete the memory from heap
     delete ptr;
     delete cptr;
     delete conststudent;
}
     /*Output :explore the possibilities with normal heap pointer *ptr
 Students rollNo set by Default constructor : 50595
 Students Grade set by Default constructor : A
 Students rollNo set by SetRollNo() function :6060
 Students name set by setgrade() function:B
 explore the possibilities with pointer *conststudentto
 constant object Student
 Display Grade …A
 explore the possibilities with const pointer *cptr to
 constant object Student
 cptr-> GetGrade()..A/*

So why do we use constant pointers?

We do so because constant pointers cannot call non-constant member functions, i.e. member functions that can alter member data. So our member data is safe. While const pointer to constant object is possible, it is tedious and cumbersome. Instead, the same can be achieved more elegantly if we use reference. Remember, insinuations wherein we cannot reassign pointers, reference is a better alternative.

10.8 Passing of Objects by Reference and Pointers to a Function

We are aware that normal variables can be passed to and from function with pass by value and pass by reference. We have also learnt in Chapter 6 on pointers that passing by reference involves passing either by pointer or reference (address). Objects, because they occupy good amount of memory, have to be passed as call by reference. More so because if you use call by value, a copy is made when an object is passed on to function and another copy of the object is made when function returns an object to calling function. What a waste of precious memory! Not only that, other resources are also employed such as calling a copy constructor and destructor. Your program is busy doing these unnecessary jobs when you use call by value.

In our next example, we will study the implications of call by value, call by reference on objects calling functions. For this, we would declare three different functions outside the class and show the costs and efficiencies involved in different modes of invoking the function.

Student FindGrade( Student std); //call by value
Student * FindGrPtr(Student *std); // call by ref using pointers
Student & FindGrRef (Student &std); // call by reference using reference

Also note that we have declared all the member data as pointers.

int *rollNo; float *total; char *grade;

Constructor allocates memory in Heap memory with new operator as shown below

Student::Student(int n, float t, char c)
{ cout<<”
 This is Student(int,float,char) constructor…
”;
rollNo= new int(n);
grade= new char(c);
total=new float(t);
}

Destructor is called whenever we have to destroy the object. But remember, our data members like rollNo, grade, and total are also residing on the heap memory. Therefore, we have to explicitly delete them

~Student(){cout<<”
 This is destructor..
”;
delete rollNo;delete grade;delete total;
} // destructor

Copy constructor gets data items from src and allocates space on heap with new operator.

Student::Student(Student &src) // src means source
{ cout<<”This is copy constructor..
”;
rollNo=new int(*(src.rollNo));
grade=new char(*(src.grade));
total=new float(*(src.total));
}

src is the name we use to denote that it is a source file. Generally left-hand side is reserved for current object, i.e. target and source is placed on the right-hand side. We are creating data members on heap memory. Therefore, rollNo and grade and total have been allocated space using new operator. Note that as we are within member function, i.e. constructor, we could use *src.rollNo directly without going through public accessory function ( *src.GetRollNo())

We have created an object of Student

Student std; // an object made .Therefore, constructor will be called

As our data members are pointers, cout statements in the main program are

cout<<”
 RollNO:”<<*(std.GetRollNo())<<”	”
      <<“Total:“<<*(std.GetTotal())<<endl;

When we use call by value by statement FindGrade(std); copy constructors are invoked twice: once for forwarding the object to function and once for return from the function. Normally changes made in the function are not reflected in the calling function in case of call by value. But in this case we are returning the object to called function by statement : return std; hence grade changes are reflected in the main program.

A call to a function FindGrPtr( Student *std) means we are resorting to pass by reference using pointer. In this case, copy constructors and destructors are not involved at all . This means that primary memory and computer time is conserved. As this is pass by reference using pointer, value set by local variable(grade) is reflected in the main. As we are using pointer to object and data members are all pointers we have to use indirection operator to access data members : cout<<*(std2->GetGrade())

Student *std2=new Student(); // std2 is created on heap .
std2=FindGrPtr(std2); // pass by reference pointer method
cout<<”
 Students Grade set by FindGrPtr() : “
      <<*(std2->GetGrade())<<endl; //pass by ref ptr

A call to a function Student & FindGrRef (Student &std); means that we are resorting to pass by reference using & operator. In this case, copy constructors and destructors are not involved at all. This means that primary memory and computer time is conserved. As this is pass by reference using address, value set by local variable(grade) is reflected in the main.

Student *std2=new Student(); // std2 is created on heap .
std2=FindGrPtr(std2); // pass by reference pointer method
cout<<”
 Students Grade set by FindGrPtr() : “

      <<*(std2->GetGrade())<<endl; //pass by ref ptr

 

Example 10.13:   refptr.cpp To Demonstrate Passing of Objects by Reference and Pass by Pointers and Pass by Value. Constructors and Destructors of a Class

#include<iostream>
using namespace std;
//declare a class called Student
class Student
 {  public:
    Student();
    Student(int n, float t, char c);
    Student(Student &);
    ~Student(){cout<<”
 This is destructor..
”;
    delete rollNo;delete grade;delete total;} // Default destructor
    int *GetRollNo() const { return rollNo;}
    void SetRollNo ( int n) { *rollNo=n;}
    char *GetGrade() const { return grade;}
    void SetGrade( char p) { *grade=p;}
    float * GetTotal() const { return total;}
    void SetTotal( float t) { *total=t;}
private:
    int *rollNo;
    float *total;
    char *grade;
};
    Student::Student()
    { cout<<"
This is default constructor…
";
           rollNo= new int;
           grade= new char(‘D’); // default Grade
           total=new float;
    }
    Student::Student(int n, float t, char c)
    { cout<<"
 This is Student(int,float,char) constructor…
";
           rollNo= new int(n);
           grade= new char(c);
           total=new float(t);
    }
    Student::Student(Student &src) // src means source
    { cout<<"This is copy constructor..
";
           rollNo=new int(*(src.rollNo));
           grade=new char(*(src.grade));
           total=new float(*(src.total));
    }
// Three non-member functions
Student FindGrade( Student std); //call by value
Student * FindGrPtr(Student *std); // call by ref using pointers
Student & FindGrRef (Student &std); // call by reference using reference
void main()
{ cout<<"
 create an ordinary object called std for Student class..
";
    Student std; // an object made. Therefore constructor will be called Student *std2=new Student(); // std2 is created on heap.
std.SetRollNo(50);
    std.SetTotal(99.0);
cout<<”
 RollNO:”<<*(std.GetRollNo())<<”	”
    <<”Total:”<<*(std.GetTotal())<<endl;
// now call a function FindGrade(Student std)
// See how copy constructors are involved one for forward copy and one for return
// see also how value set by local variable(grade =A) is reflected in the main
// because you are returning the object by value using statement return std
// you should also see two destructors
     FindGrade(std);
     cout<<”
 Students Grade set by FindGrade() :”
           <<*(std.GetGrade())<<endl;
// now call a functon FindGrPtr( Student *std)
// See how copy constructors and destructors are not involved at all
// see also how value set by local variable(grade) is reflected in the main
     std2=FindGrPtr(std2); // pass by reference pointer method
     cout<<”
 Students Grade set by FindGrPtr() : “
           <<*(std2->GetGrade())<<endl; //pass by ref ptr
// now call a function FindGrref(Student & std)
// See how copy constructors and destructors are not involved at all
// see also how value set by local variable(grade) is reflected in the main
     FindGrRef(std); // pass by reference reference method
     cout<<”
 Students Grade set by FindGrRef() :”
           <<*(std.GetGrade())<<endl; // pass by reference - reference */
     }// end of main
// Define functions
Student FindGrade( Student std)
    { cout<<”
 FindGrade( Student std) function …
”;
      cout<<” 
 Students Grade set by FindGrade() : 
”;
      std.SetGrade(‘A’);
      cout<<”
 inside FindGrade..:”<<*(std.GetGrade())<<endl;
      return std;
}
Student * FindGrPtr(Student *std)
{     std->SetGrade(‘B’);
      cout<<”
 Inside FindGrPtr() : “<<*(std->GetGrade())<<endl;
      return std;
}
Student & FindGrRef ( Student &std)
{ std.SetGrade(‘C’);
  cout<<”
 Inside FindGrRef() : “<<*(std.GetGrade())<<endl;
  return std;
}
/*Output :This is copy constructor..
FindGrade( Student std) function …
Students Grade set by FindGrade() :
inside FindGrade..:A
This is copy constructor..
This is destructor..
This is destructor..
Students Grade set by FindGrade() :D
Inside FindGrPtr() : B
Students Grade set by FindGrPtr() : B
Inside FindGrRef() : C
Students Grade set by FindGrRef() :C
This is destructor..*/

10.9 Constant Pointers and Constant References

Recall that in the above example function Student * FindGrPtr(Student *std); receives the object by reference using pointers. It also amends the Grade. What if we want the function to receive the object by reference because of efficiency and yet should not be able to change the values. Clearly the solution is to pass a constant pointer to Student and thus FindGrPtr () not amend the object. This is because of the stipulation that a constant pointer can only call a constant function and constant function by definition cannot alter the values.

const Student * const FindGrPtr(const Student * const std);
const Student & FindGrRef (const Student &std);

Call by ref using constant pointers and also constant object. The second call involves call by reference using & operator and also constant object Student. Look at the program presented below to understand the concepts involved better.

 

Example 10.14:   constrefptr.cpp To Demonstrate Constant Pointer and Constant Reference and Constant Object. Constructors and Destructors of a Class

//constptrref.cpp
#include<iostream>
using namespace std;
//declare a class called Student
class Student
{ public:
   Student();
   Student(int n, float t, char c);
   Student(Student &);
   ~Student(){cout<<”
 This is destructor..
”;
   delete rollNo;delete grade;delete total;} // Default destructor
   int *GetRollNo() const { return rollNo;}
   void SetRollNo ( int n) { *rollNo=n;}
   char *GetGrade() const { return grade;}
   void SetGrade( char p) { *grade=p;}
   float * GetTotal() const { return total;}
   void SetTotal( float t) { *total=t;}
private:
   int *rollNo;
   float *total;
   char *grade;
};
Student::Student()
  { cout<<"
This is default constructor…
";
    rollNo= new int;
    grade= new char(‘D’); // default Grade
    total=new float;
}
Student::Student(int n, float t, char c)
  { cout<<"
 This is Student(int,float,char) constructor…
";
  rollNo= new int(n);
  grade= new char(c);
  total=new float(t);
  }
 Student::Student(Student &src) // src means source
 {
  cout<<"This is copy constructor..
";
  rollNo=new int(*(src.rollNo));
  grade=new char(*(src.grade));
  total=new float(*(src.total));
}
  const Student * const FindGrPtr(const Student * const std);
  const Student & FindGrRef (const Student &std);
 void main()
 { cout<<"
 create an ordinary objet called std for Student class..
";
   Student std; // an object made . Constructor will be called
   std.SetRollNo(50);
   std.SetTotal(99.0);
   cout<<"
 RollNO :"<<*std.GetRollNo()<<"	"<<"Total :"
         <<*std.GetTotal()
     <<"Grade : "<<*std.GetGrade() <<endl;
     // now call const Student * const FindGrPtr(const Student * const std);
     FindGrPtr(& std); // pass by reference pointer method
     cout<<"
 Students Grade after return from FindGrPtr() : "
         <<*std.GetGrade()<<endl;
     // now call a function : const Student & FindGrRef (const Student &std);
     FindGrRef(std); // pass by reference reference method
     cout<<"
 Students Grade after returning from FindGrRef() :"
         <<*std.GetGrade()<<endl;
     }// end of main
 const Student * const FindGrPtr(const Student * const std)
 { //std->SetGrade(‘B’); // clearly error constant pointer to constant obj
  cout<<"
 Inside FindGrPtr() : "<<*std->GetGrade()<<endl;
  return std;
 }
 const Student & FindGrRef ( const Student & std)
 { //std.SetGrade(‘C’); // clearly error . student is a constant obj
       cout<<"
 Inside FindGrRef() : "<<*std.GetGrade()<<endl;
       return std;
 }
 /*Output :create an ordinary objet called std for Student class..
This is default constructor…
RollNO :50 Total :99Grade : D
Inside FindGrPtr() : D
Students Grade after return from FindGrPtr() : D
Inside FindGrRef() : D
Students Grade after returning from FindGrRef() :D
This is destructor..*/

Note that in cout statements in main() and functions std.GetGrade() return a pointer of character type as per our function prototype declaration. Hence we have used dereference operator * : *std.GetGrade() or *std->GetGrade();

10.10 Static Member Data

Recall our definition of encapsulation. It is binding of member data and member functions into a single entity by class. A class has access tights defined for its data members and enjoys the benefits of protective and security features like data hiding, abstraction, etc. Further you are aware that member data is exclusive to an instance of object. For example, Student Hari cannot share the data of Student Shiva.

If we want a single data item to be available to all instances of the class, one way is to declare it as a global variable. But in that case we would lose all advantages of being a member of a class like data security, access privileges, etc.

For example, if we want a variable called count to keep track of the number of objects being created and the number of objects being deleted, how do we declare such a variable?

If we declare it in global section, we would lose benefits of being within the class. But if we declare it within the class, it becomes part of the class and hence belongs to an instance of class and cannot be shared amongst objects. Then how can the variable keep track of the number of objects being created?

Variable declared as static, though resides inside a class; it can keep track of the objects being created or destroyed. This means that it is accessible to all instances of the class. We can say that static data belongs to class and not to an object.

class Student
{ public:
Student(){count++;}
~Student(){count--;} // Default destructor
static int count; // static data member declared as public
};

Therefore, to give access to all instances of the class declare the variable as static. It does not belong to class and is not initialized along with member data when the object is created. Also note that no memory resources are allocated by static declaration made inside the class. Hence, the static variables are required to be declared globally outside the class and then only resources are allocated.

int Student::count=0; // mandatory to declare in global section

In the example shown below, we have instantiated four objects, two outside the controlling braces and two within the controlling braces. We can use static variable count with any one of the objects to get the count of objects created:

Student a,b;
{ Student ramesh, suresh;
cout<<”ramesh.count”<<ramesh.count<<”	”<<”suresh.count”
}

The life of variables is till the controlling brace brackets. Hence we would get count as 2 when we check the count after the controlling braces.

 

Example 10.15:   static1.cpp To Demonstrate Usage of Static Data Within a Class

#include<iostream>
using namespace std;
//declare a class called Student
class Student
{ public:
     Student(){count++;}
     ~Student(){count--;} // Default destructor
     static int count; // static data member declared as public
};
int Student::count=0; // mandatory to declare in global section
void main()
{
{ Student a,b; // two objects have been created
     Student ramesh, suresh;
     cout<<”ramesh.count”<<ramesh.count<<”	”<<”suresh.count”
     <<suresh.count<<endl;
     cout<<”The above result shows that static variable is available to ramesh & suresh”;
}
     cout<<”
after brace brackets :”<<endl;
     cout<<”a.count=”<<a.count<<endl;
     Student w,x,y,z;
     cout<<”
after creation of w x y z :”<<endl;
     cout<<”a.count”<<a.count<<”	”<<”b.count”<<b.count<<endl;
}
/*Output :ramesh.count4 suresh.count4
The above result shows that static variable is available to ramesh & suresh
after brace brackets :
a.count=2
after creation of w x y z :
a.count6 b.count6*/

What happens if you declare the static data as private? Quite simple. By now you must have understood that the only way to access a private data is through a public accessory function. Code is reproduced for static data type that is declared as private.

 

Example 10.16:   static2.cpp To Demonstrate Usage of Private Static Data Within a Class

#include<iostream>
using namespace std;
//declare a class called Student
class Student
 {public:
     Student(){count++;}
     ~Student(){count--;} // Default destructor
     int GetCount() const { return count;}// public function to access static private data
     private:
     static int count; // static data member declared as private
     };
     int Student::count=0; // mandatory to declare in global section
     void main()
     { Student a,b;
     { Student ramesh, suresh;
       cout<<”ramesh.count”<<ramesh.GetCount()<<”	”<<”suresh.count”
           <<suresh.GetCount()<<endl;
       cout<<”The above result shows that static variable is available to ramesh & suresh”;
     }
     cout<<”
after brace brackets :”<<endl;
     cout<<”a.count=”<<a.GetCount()<<endl; // because static private declaration
     Student w,x,y,z;
     cout<<”
after creation of w x y z :”<<endl;
     cout<<”Student.count”<<x.GetCount()<<”	”<<”y.count”<<y.GetCount()<<endl;
 }
/*Output :ramesh.count4 suresh.count4
The above result shows that static variable is available to ramesh & suresh
after brace brackets :
a.count=2
after creation of w x y z :
Student.count :6 y.count : 6*/

10.11 Static Member Functions

The data members declared as static is available for all instances of the class. That is why we could use x.GetCount() and y.GetCount() in the above program. Therefore, it really does not matter which object calls the function that displays static data.

To make it independent of object we need to define the member function as static.

static int GetCount() { return count;}// public function to access static private
cout<<Student::GetCount() // you can call static function without object
                          // by using class name and scope resolution operator

The next program illustrates the static function concept and usage.

 

Example 10.17:   static3.cpp To Demonstrate Usage of Static Member Functions Within a Class

#include<iostream>
using namespace std;
//declare a class called Student
class Student
{ public:
     Student(){count++;}
     ~Student(){count--;} // Default destructor
     static int GetCount() { return count;}// public function to access static private data
  private:
     static int count; // static data member declared as public
};
     int Student::count=0; // mandatory to declare in global section
     void main()
     { Student a,b;
     { Student ramesh, suresh;
            cout<<”Student.count”<<Student::GetCount()<<endl;
}
cout<<”
after brace brackets :”<<endl;
cout<<”Student.count=”<<Student::GetCount()<<endl;
    Student w,x,y,z;
    cout<<”
after creation of w x y z :”<<endl;
    cout<<”Student count :”<<Student::GetCount()<<endl;
 }
/*Output : Student.count4
after brace brackets :
Student.count=2
after creation of w x y z :
Student count :6
*/

10.12 Summary

  1. Class, we use in C++, to define our own data type. Class data types can be of different data types.
  2. Object is a variable of data type class.
  3. A class therefore allows us to encapsulate member functions and member data into a single entity called object.
  4. Encapsulation is binding of data and member function into objects by a class.
  5. Access privileges are public, private and protected. Members declared as public are available to all, whereas members declared as private are only available to instances of the class. Protected members are private to all but public to descendants, i.e. derived classes in inheritance relation.
  6. The only way to access private member data is through public accessory functions.
  7. Use scope resolution operator :: to define member functions outside the class.
  8. Member functions declared and defined inside a class are treated as inline functions, though explicitly not stated.
  9. Constructors and destructors have the same name of the class but they have no return types.
  10. Friend function carries a keyword friend, even if declared inside the class does not belong to class. It has access to all private data members directly without going through the public accessory functions. When defining friend functions outside the class, there is no need to use scope resolution operator as the friend function does not belong to class.
  11. Containers are provided by C++ to achieve reusability of code. Containments are also called composition or aggregation. Composition is a ‘has’-type of relation.
  12. Objects and data members can be allocated space on Heap memory using new operator and released using delete operator. Indirection operator ->is used to access members on heap.
  13. This pointer is a hidden pointer that is forwarded to a function. It is called this pointer because it refers to this object that has invoked the function.
  14. Constant pointers and constant objects are used to ensure data security and integrity. Constant pointers can only call constant functions.
  15. Objects are passed by reference, either by reference or through pointers.
  16. When using const object and no reassignment is involved it is better to use reference method that is easy to use and elegant rather than const pointer to constant object.
  17. Static member data though resided inside a class does not belong to class . It is available to all instances of the class. It is mandatory to define in global section static member data so that memory resources can be allocated.
  18. To make invoking of member functions independent of objects we need to declare public functions handling static data as static functions.

Exercise Questions

Objective Questions

  1. A constructor is called whenever
    1. An object is declared
    2. An object is used
    3. A class is declared
    4. A class is used
  2. A class having no name
    1. Is not allowed
    2. Cannot have a constructor
    3. Cannot have a destructor
    4. Cannot be passed as argument
  3. Constructors can take arguments
    1. Zero arguments
    2. Two arguments
    3. No arguments
    4. Any number of arguments
  4. Destructors can take arguments T
    1. One argument
    2. Two arguments
    3. No arguments
    4. Any number of arguments
  5. Constructor can be overloaded while destructor cannot be overloaded     True/False
  6. Constructors are used to create data members.     True/False
  7. Constructors return void data type.     True/False
  8. Member functions declared and defined inside a class are inline though not explicitly defined.     True/False
  9. In C++, a function declared within a class is called
    1. Inline function
    2. Member function
    3. Contained function
    4. Class function
  10. The default access specifies for data members in C++ is
    1. Public
    2. Private
    3. Protected
    4. Inherited
  11. Declaring a friend function inside a class allows the friend function to access
    1. Private data of all member objects of the class
    2. Private member functions of all member objects of the class
    3. Both a and b
    4. None of the above
  12. Static variable declared as private is available to all instances of the class
    1. Through public function
    2. Through public function declared as static
    3. Directly without public function
    4. None of above
  13. 13) A static function can handle
    1. Non-static data
    2. Only static data
    3. Private data
    4. Public data.
  14. Class declaration and definition and is placed above void main(). Which one of the following statements are NOT true?
    1. It is required by all functions
    2. It is a global declaration
    3. Space available
    4. They are global declarations and available to all
  15. Const pointer can call
    1. Non-constant function
    2. Const function
    3. Any function
    4. None
  16. If object is declared constant then this pointer is a constant pointer     True/False
  17. Dynamic memory can be allocated with
    1. Pointers only
    2. Reference operator only
    3. Both a and b
    4. None
  18. Constant this pointer can call
    1. Non-constant function
    2. Const function
    3. Any function
    4. None

    Short-answer Questions

  19. Distinguish between private and public access specifiers.
  20. Distinguish a class and an object. Why is scope resolution operator employed in C++?
  21. Explain data hiding and encapsulation.
  22. Explain why private variables cannot be accessed outside the class directly.
  23. What is the solution provided by language C++? For problem at 4.
  24. Explain constructor overloading.
  25. Explain the difference between default constructor and constructor with arguments.
  26. What is a friend function? How is it useful?
  27. Explain static data variable.
  28. Distinguish a static data and a global data.
  29. What is a container class? Explain with examples.
  30. Explain the use of this pointer.
  31. Why are constant pointers deployed?
  32. Explain the context under which constant pointer to constant object can be deployed.
  33. Constant pointer can only invoke a constant function. Why this restriction?
  34. How do you create objects on heap memory? Explain with examples.
  35. How do you create member data on heap memory? Explain with examples
  36. Differentiate Const pointer to data and pointer to constant data.

    Long-answer Questions

  37. Declare a class called Account with data members, accNo, name, balance. Declare a data members as private and member functions as public. Declare a member function called Transact which will allow withdrawal of amount and then display the balance.
  38. Rewrite the above code with a private member function called DisplayTrDate() that will be invoked by withdraw function and will display transaction date.
  39. Implement a class called FractionNo with suitable constructors and destructors. Include functionality like add, multiply and inverse.
  40. Declare a Point class inside a class Rectangle and calculate the area of the rectangle.
  41. Write code for creating objects of two employees with idNo, name, basicPay. Demonstrate the use of constructor, copy constructor.
  42. Rewrite the code for sl 5 with object and member data on the heap memory.
  43. Write a class based cpp to calculate the grades of n number of students. There are 2 mid-term examinations. Each mid-term examination consists of one online for 20 marks and one subjective paper for 20 marks. For internal marks consider the best of the online and the best of subjective papers. External papers to have 60% weight. Declare grade A for 80% and above, Grade B for 60 to 79%, Grade C for others. Use a private member function to determine the grade of the student.
  44. Declare a class called a rational number, defined as two integer variables called numerator and denominator, and include functionality for + ., −, *, / of two rational numbers. Use friend function for mathematical operations.
  45. Implement a class to represent a Circle that holds radius, x, y(center coordinates) and functions to calculate area and circumference. Use containment concept.
  46. Use a class called counter. Declare a private static variable called count. Use it through public function and display the no. of objects created. Constructor and destructor must keep track of count addition on creation and subtraction on deletion.

Solutions to Objective Questions

  1. a
  2. a
  3. d
  4. c
  5. True
  6. False
  7. False
  8. True
  9. b
  10. b
  11. c
  12. b
  13. b
  14. c
  15. b
  16. True
  17. a
  18. b
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.15.231.194