Lecture
No.14 CS 304 oop            
 


Consider
the following implementation of the student class we discussed in previous
lectures,



Composition

If one object is part of another object
(relationship of part and whole) in composition lifetime of one object depends
upon the other. The part objects are essential components of the whole.
For example person is composed of hands,
eyes, feet so on.

In student class we assigning dynamic memory for
variable name using new operator as shown,

class
Student{
private:
  float gpa;
  char * name;
  int rollNumber;
public:
  Student(char * = NULL, int = 0, float = 0.0);
  Student(const Student & st);
  const char * GetName() const;
  // never return handle of private data
members or private member functions
  ~Student();
 
};





Student::Student(char
* _name, int roll, float          g)
{
            cout <<
"Constructor::Student..\n";
            if (!_name){
                        name = new
char[strlen(_name)+1];
                        strcpy(name,_name);
            }
            else name = NULL;
            rollNumber = roll;
            gpa = g;
  }
 

Student::Student(const
Student & st){
   if(str.name != NULL){
       name = new char[strlen(st.name) + 1];
       strcpy(name, st.name);
   }
   else name = NULL;
   rollNumber = st.roll;
   gpa = st.g;
}

 
  const char * Student::GetName(){
     return name;
  }

  // never return handle of private data
members or private member functions const ensures that private data members
will not be changed


  Student::~Student(){
            delete [] name; // deleting name
array
  }


In
C++ “it is all about code reuse”
Composition is Creating objects of one class inside another
class
Has
a

relationship:
Bird
has a beak
Student
has a name

Composition

Now
we change code slightly replacing name char * by String so that it is whole
object of class String as it qualifies to be an object because we have to apply
many operations on it like string dynamic creation and deletion, string copy
using deep copy, searching a substring and so on….

Conceptual
notation:


Composition

Now we see string class code to see how it
simplifies original Student object and how we have used composition here,

class
String{
  private:
            char * ptr;
  public:
            String(); // default constructor
            String(const String &); // copy
constructor
            void SetString(const char *); //
setter function
            const
char * GetString() const;
//
getter function returning const pointer to data member ptr
            ~String()
           
};
  String::String(){
            cout <<
"Constructor::String..\n";
            ptr = NULL;
  }
 
  String::String(const String & str){
     if(str.ptr != NULL){
             ptr = new char[strlen(str.ptr)+1];
             strcpy(ptr, str.ptr);
     }
     else ptr = NULL;
  }
  void String::SetString(const char * str){
            if(ptr
!= NULL){
                        delete [] ptr;   
                        ptr = NULL;
            }
            if(str != NULL){         
                        ptr = new
char[strlen(str)+1];
                        strcpy(ptr, str);
            }
  }

issue
of memory leakage (inaccessible memory)
if
we simply set pointer here
memory
will be outside of our object many cause problems later
user
still has pointer of passed value it can itself modify it

We
resolve these two issues in SetString by allocating new memory and deleting
previous memory.

const
char * String::GetString()const{
     return ptr;
 }
 String::~String(){
            delete [] ptr;
            cout <<"Destructor::String..\n";
 }

Make
pointer equal to NULL as well any where you delete dynamic memory.




Now
consider the code of Student class again, now by adding composed string object
our code has been simplified very much, (we will use methods of composed object
simply by calling them where needed)

class
Student{
private:
  float gpa;
  int rollNumber;
  String name;
public:
  Student(char* =NULL, int=0,float=0.0);
  Student(const Student &);
  void SetName(const char *);
  String GetName() const;
  const char * GetNamePtr() const;
  ~Student();
 
};

Student
::Student(char * _name,     int roll,
float g){
            cout
<<"Constructor::Student..\n";
            name.SetString(_name);
            rollNumber = roll;
            gpa = g;
  }
 
Student::Student(const
Student & s){
            name.SetString(s.name.GetString());
            gpa = s.gpa;
            rollNumber = s.rollNumber;
  }

Explanation:

  1. name.SetString(s.name.GetString());
// setting
composed name of newly created object

  1. name.SetString(s.name.GetString());
//accessing the
composed object string name of object to be copied

  1. name.SetString(s.name.GetString());
//accessing the
value of composed object string name by calling its member function GetString

  1. name.SetString(s.name.GetString());
//overall result
: the value of composed object string of object to be copied will be copied to
newly created object composed object string.


const
char * Student::GetNamePtr() const{
      return name.GetString();
  }

  void Student::SetName(const char * n){
            name.SetString(n);
  }
 
  Student::~Student(){
            cout <<"Destructor::Student..\n";
  }

void
main(){
            Student *aStudent=new Student("Fakhir",
899, 3.1);
            cout << endl;
            cout << “Name:” <<
aStudent->GetNamePtr() << “\n”;
}


   Output:


 

Constructor::String..

Constructor::Student..

 

Name: 
Fakhir

Destructor::Student..

Destructor::String..





   Important Points:

  1. We can access methods of composed object in the same way as we can
    access methods of other objects.

            Name of composed object.MemberFunction

  1. Member functions of a class can access its private data members like,

Student::Student(const
Student & s){

           name.SetString(s.name.GetString());
   
// accessing
private member String name of student using its object s and then
accessing String name member function GetString to access string
value two methods calss in one line

            gpa = s.gpa;   
// accessing
private members of student in student member function    

            rollNo = s.rollNo;
// accessing
private members of student in student member function                
  }


Constructors
& Composition


Constructors
of the sub-objects are always executed before the constructors of the master
class

Example:

As
you see the example output of program given above,

Output:


 

Constructor::String..

Constructor::Student..

 

Name: 
Fakhir

Destructor::Student..

Destructor::String..



Constructor
for the sub-object name is executed before the constructor of Student and
destructor of sub-object is called after destructor of student. It is logical
as composing object has to contain composed object so composed object should be
created first and then composing object. Similarly while destructing objects we
composing object is destructed first and then composed object as shown in
diagram below,





                                                
Composition


Constructor
calling:

Constructors
are called from composed objects to composing objects.



Destructor
calling:


Destructors
are called from composing objects to composed objects.

Post a Comment

Don't Forget To Join My FB Group VU Vicky
THANK YOU :)

Previous Post Next Post