









Study with the several resources on Docsity
Earn points by helping other students or get them with a premium plan
Prepare for your exams
Study with the several resources on Docsity
Earn points to download
Earn points by helping other students or get them with a premium plan
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
1 / 15
This page cannot be seen from the preview
Don't miss anything!










Objects as Class Members Example 1 Example 2 Advantages of Objects as Class Members Structures as Class Members Classes inside Classes Tips
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 {
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