Objects as Class Members-Introduction To Programming-Lecture Notes, Study notes of Computer Programming

A program is a precise sequence of steps to solve a particular problem. This course includes basic programming structure like loops, operator, memory allocation, reference, pointers etc. It teaches how to be a good programmer. This lecture handout is about: Object, Class, Members, Structures, User, defined, Data, Type, Construction, Program, Destructions, Order, Instance, Default, Initializer

Typology: Study notes

2011/2012

Uploaded on 08/06/2012

anchal
anchal 🇮🇳

4.6

(9)

95 documents

1 / 15

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
482
Lecture No. 40
Reading Material
Deitel & Deitel - C++ How to Program Chapter 7
7.3, 7.4
Summary
x Objects as Class Members
x Example 1
x Example 2
x Advantages of Objects as Class Members
x Structures as Class Members
x Classes inside Classes
x Tips
Objects as Class Members
A class is a user defined data type and it can be used inside other classes in the same
way as native data types are used. Thus we can create classes that contain objects of
other classes as data members.
When one class contains objects of other classes, it becomes mandatory to understand
how and in what sequence the contained and containing objects are constructed. An
important point in construction of an object is that the contained data members of the
object (regardless whether they are native or user defined data types) are constructed
before the object itself. The order of destruction of an object is reverse to this
construction order, where the containing object is destroyed first before the contained
objects.
To elaborate the construction and destruction orders of objects, we take a class A and
contain its instance (object) in another class B.
/* This program illustrates the construction and destruction orders of objects. */
#include <iostream.h>
class A
{
docsity.com
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff

Partial preview of the text

Download Objects as Class Members-Introduction To Programming-Lecture Notes and more Study notes Computer Programming in PDF only on Docsity!

Lecture No. 40

Reading Material

Deitel & Deitel - C++ How to Program Chapter 7

Summary

 Objects as Class Members  Example 1  Example 2  Advantages of Objects as Class Members  Structures as Class Members  Classes inside Classes  Tips

Objects as Class Members

A class is a user defined data type and it can be used inside other classes in the same way as native data types are used. Thus we can create classes that contain objects of other classes as data members. When one class contains objects of other classes, it becomes mandatory to understand how and in what sequence the contained and containing objects are constructed. An important point in construction of an object is that the contained data members of the object (regardless whether they are native or user defined data types) are constructed before the object itself. The order of destruction of an object is reverse to this construction order, where the containing object is destroyed first before the contained objects. To elaborate the construction and destruction orders of objects, we take a class A and contain its instance (object) in another class B.

/* This program illustrates the construction and destruction orders of objects. */

#include <iostream.h>

class A {

docsity.com

public: A() { cout << "\n A Constructor ..."; }

~A() { cout << "\n A Destructor ..."; } };

class B { public: B() { cout << "\n B Constructor ..."; }

~B() { cout << "\n B Destructor ..."; }

private: A a; };

void main(void) { B b; }

The output of this code is as follows: A Constructor ... B Constructor ... B Destructor ... A Destructor ...

In the code above, we have contained an instance of the class A inside class B. In the main function, we have only created an object of the class B. From the output, we can see the first line that the contained object a ’s default constructor is called before the default constructor of the class B. At destruction time, the destructor of the class B is called first before A ’s. Note that the contained object ‘ a’ of class A is constructed by calling the default constructor. Hence, we have found one way of constructing contained objects by means of default constructors and then setting the values of data members by calling setter methods of the object. But this is cumbersome and wasteful, we have a better way provided by the language to initialize

docsity.com

of execution, let us have another Date object drvLicenseDate declared after birthday object in the PersonInfo class:

/* This program illustrates the initializer list, order of execution of constructor’s inside the list. */

#include <iostream.h> #include <string.h>

class Date { public: Date( ); Date(int month, int day, int year); ~Date ( );

private: int month, day, year; };

Date::Date( ) { cout << "\n Date -- Default constructor called ..."; month = day = year = 0; }

Date::Date(int month, int day, int year) { cout << "\n Date -- Constructor with month=" << month << ", day= " << day << ", year= " << year << " called ..."; this->month = month; this->day = day; this->year = year; }

Date::~Date ( ) { cout << "\n Date -- Destructor called ..."; }

class PersonInfo { public: // public member functions... PersonInfo( char * nm, char * addr, int month, int day, int year, int licMonth, int licDay, int licYear ); PersonInfo::~PersonInfo();

private: char name[30];

docsity.com

char address[60]; // member objects Date birthday; Date drvLicenseDate; };

PersonInfo::PersonInfo( char * nm, char * addr, int month, int day, int year, int licMonth, int licDay, int licYear ) : drvLicenseDate( licMonth, licDay, licYear), birthday( month, day, year ) // Above line is initializer list { cout << "\n PersonInfo -- Constructor called ..."; strncpy( name, nm, 30 ); strncpy( address, addr, 60 ); }

PersonInfo::~PersonInfo() { cout << "\n PersonInfo -- Destructor called ..."; }

main(void) { PersonInfo pi("Abbas", "12-Y, DHS, Lahore, Pakistan", 12, 12, 1972, 12, 10, 1992); }

The output of this program is: Date -- Constructor with month=12, day= 12, year= 1972 called ... Date -- Constructor with month=12, day= 10, year= 1992 called ... PersonInfo -- Constructor called ... PersonInfo -- Destructor called ... Date -- Destructor called ... Date -- Destructor called ...

Because birthday is declared before drvLicenseDate , it is clear from the output that the constructor for birthday is called first and then for the drvLicenseDate object, although drvLicenseDate is present before birthday in the initializer list.

Example 2

Let’s take another example to work with the size of a matrix. We declare a Column class first then a Row class. Row class contains an instance of Column class to store the number of columns (number of elements) inside one Row instance. Further, the Matrix class contains an instance of Row class. See the code below. /* Program to illustrate the initialization lists, construction and destruction sequences of contained and containing objects. */

docsity.com

void Row :: showSize ( ) { col.showSize ( ) ; cout << "Row size is : " << size << endl << endl ;

} void Row :: setSize ( int sz ) { size = sz ; }

class Matrix { private : Row row ; public : Matrix ( int rowSize, int colSize ) : row( rowSize, colSize ) { cout << "Matrix created" << endl << endl ; } ~Matrix ( ) { cout << "Matrix destroyed" << endl << endl ; } void displayMatrixSize ( ) ;

} ;

void Matrix :: displayMatrixSize ( ) { row.showSize ( ) ; }

void f( ) { Matrix matrix(3, 4) ; matrix.displayMatrixSize ( ) ; }

int main() { f( ); system("PAUSE"); return 0; }

The output of the program is as follows: Column created

docsity.com

Row created

Matrix created

Column size is : 4

Row size is : 3

Matrix destroyed

Row destroyed

Column destroyed

Press any key to continue...

Notice the construction sequence of objects. In order to create a Matrix object, a Row object is created first and to create a Row object, a Column object is created. So the contained object Column is constructed first of all, then comes the Row object and finally the Matrix object. At destruction time, the very first object to destroy is the last object constructed, which is the Matrix object. The second object destroyed is Row object and then the Column object at the end. See also the use of initializer list in the code, how the colSize and rowSize arguments are passed to the constructors.

The public data members of a contained object can also be accessed from outside of the containing class. For example, if row object inside Matrix class is declared as public and has a public variable named size then it can be accessed using the dot operator (“.”) as:

int main ( void ) { Matrix matrix ( 4, 5 ) ; Matrix.row.size = 8 ; }

Advantages of Objects as Class Members

docsity.com

~VehicleParts() { cout << "\n VehicleParts - destructor" << endl; }

} ;

class Vehicle {

private : VehicleParts vehicleParts ;

public : Vehicle( ) { cout << "\n Vehicle - default constructor" << endl; } Vehicle( int a, int b ) : vehicleParts( a, b ) { cout << "\n Vehicle - parameterized constructor"; } ~Vehicle( ) { cout << "\n Vehicle - destructor"; } void setPartsNum ( int a, int b ) { vehicleParts.wheels = a ; vehicleParts.seats = b ;

} void displayNumVehicleParts ( ) { /* The data members of the structure are public, therefore, directly accessible from outside. */ cout << "\n Number of wheels for this vehicle are " << vehicleParts.wheels; cout << "\n Number of seats for this vehicle are " << vehicleParts.seats << endl;

}

} ;

void f() { Vehicle car( 4, 2 ) ; car.displayNumVehicleParts( ) ; }

docsity.com

f(); system ( "PAUSE" ) ; }

The output of the program is: VehicleParts - parameterized constructor Vehicle - parameterized constructor Number of wheels for this vehicle are 4 Number of seats for this vehicle are 2

Vehicle - destructor VehicleParts - destructor Press any key to continue...

Classes inside Classes

In C language, structures can be defined inside structures, Similarly in C++, we can have structures or classes defined inside classes. Classes defined within other classes are called nested classes. A nested class is written exactly in the same way as a normal class. We write its data members, member functions, constructors and destructors but no memory is allocated for a nested class unless an instance of it is created. C++ allows multiple levels of nesting. Importantly, we should be clear about the visibility of the nested class. If a class is nested inside the public section of a class, it is visible outside the outer (enclosed) class. If it is nested in the private section, it is only visible to the members of the outer class. The outer class has no special privileges with respect to the inner class. So, the inner class still has full control over the accessibility of its members by the outer class. Interestingly, the friend operator can be used to declare enclosed class as a friend of inner class to provide access to inner class’s private members. This operator is used in the same way as we use it for other classes that are not nested. We can also make the inner class to access the private members of enclosed class by declaring the inner class as a friend of outer class. The reason of nesting classes within other classes is simply to keep associated classes together for easier manipulation of the objects.

/* This program illustrates the nested classes */

#include <iostream.h> #include <stdlib.h>

class Surround { public : class FirstWithin

main()

docsity.com

int main() { f(); cout << endl << " "; system("PAUSE"); return 0; }

The output of the program is as follows: SecondWithin - default constructor FirstWithin - default constructor FirstWithin - default constructor FirstWithin - destructor FirstWithin - destructor SecondWithin - destructor Press any key to continue...

Notice the access specifier ( :: ) usage in function f() to access the members of inner class. The class FirstWithin is visible both outside and inside Surround. The class FirstWithin has therefore global scope. The constructor FirstWithin() and the member function getVar() of the class FirstWithin are also globally visible. The int variable data member is only visible for the members of the class FirstWithin as it is declared private. Neither the members of Surround nor the members of SecondWithin can access the variable of the class FirstWithin directly. The class SecondWithin is visible only inside Surround. The public members of the class SecondWithin canalso be used by the members of the class FirstWithin , as nested classes can be considered members of their surrounding class. The constructor SecondWithin() and the member function getVar() of the class SecondWithin can also only be reached by the members of Surround (and by the members of its nested classes). The int variable data member of the class SecondWithin is only visible to the members of the class SecondWithin. Neither the members of Surround nor the members of FirstWithin can access the variable of the class SecondWithin directly. The nested classes can be considered members of the surrounding class, but the members of nested classes are not members of the surrounding class. So, a member of the class Surround may not access FirstWithin::getVar() directly. The nested classes are only available as type names. They do not imply as objects containment by the surrounding class. If a member of the surrounding class uses a (non-static) member of a nested class then a pointer to a nested class object or a nested class data member is defined in the surrounding class. The pointer is further used by the members of the surrounding class to access members of the nested class.

It is important to know how do we define Member functions of nested classes. They may be defined as inline functions or they can also be defined outside of their surrounding class. Consider the constructor of the class FirstWithin in the previous example.

docsity.com

The constructor FirstWithin() is defined in the class FirstWithin , which is, in turn, defined within the class Surround. Consequently, the class scopes of the two classes must be used to define a constructor as the following:

Surround :: FirstWithin :: FirstWithin ( ) { variable = 0 ; } The classes FirstWithin and SecondWithin are both nested within Surround , and can be considered members of the surrounding class. Since members of a class may directly refer to each other, members of the class SecondWithin can refer to public members of the class FirstWithin but they cannot access private members of the FirstWithin unless SecondWithin is declared as a friend of FirstWithin. See the code snippet below, we have used friend operator here extensively so that all the three classes Surround , FirstWithin and SecondWithin can access private members of each other.

class Surround { class SecondWithin ; public : class FirstWithin { friend class Surround ; friend class SecondWithin ; public : int getValue() { Surround :: variable = SecondWithin :: variable ; return (variable); } private : static int variable ; } ; friend class FirstWithin ; int getValue ( ) { FirstWithin :: variable = SecondWithin :: variable ; return (variable) ; } private : class SecondWithin { friend class Surround ; friend class FirstWithin ; public : int getValue ( ) {

docsity.com