1 of 83

OBJECT ORIENTED PROGRAMMING IN C++ �[UNIT-II]

U4.1

2 of 83

Learning Objectives

  • Creating a class with different access specifier
  • Defining member functions
  • Using objects
  • Inline member functions
  • Nested member functions
  • Static data member
  • Static member functions
  • Nested Class
  • Making functions friendly to a function
  • Bridge functions
  • Function returning objects

U4.2

3 of 83

There are three kind of access control specifiers:

  • Private
  • Public
  • Protected

Data Hiding

U4.3

4 of 83

#include <iostream.h>

class student

{

private:

int rollno;

char name[20];

void setdata(int rn, char* namein );

void outdata();

};

void main(){

student s1;

s1.setdata(1, “xx”); //can’t access

s1.outdata(); //can’t access

}

Program to Private Access

U4.4

5 of 83

Protected Members

Access control is similar to private members, has more significance in Inheritance.

U4.5

6 of 83

Protected Members Contd..

#include <iostream.h>

class student

{

protected:

int rollno;

char name[20];

void setdata(int rn, char *namein);

void outdata();

};

void main()

{

student s1;

s1.setdata(1, “xx”); //can’t access protected (same as private)

s1.outdata(); //can’t access

}

U4.6

7 of 83

Public Members Contd..

#include <iostream.h>

class student

{

public:

int rollno;

char name[20];

void setdata(int rn, char *namein);

void outdata();

};

void main()

{student s1;

s1.rollno; // can access public data

s1.setdata(1, “xx”); //can access public function

s1.outdata(); //can access public function

}

U4.7

8 of 83

EMPTY CLASSES / STUB

A class that has neither data nor code.

e.g; class xyz { };

class abc

{

};

At initial level of project, some of the classes are not fully identified or not fully implemented, hence they are implemented as empty class.

Important for Exception Handling.

U4.8

9 of 83

Passing Objects as Arguments

An object can be passed as an argument to a function by the following way

  • Pass-by-value
  • Pass-by-reference
  • Pass-by pointer

Returning Objects from functions:

  • It is possible to return objects from functions.

Syntax is similar to that of returning variables

from function.

U4.9

10 of 83

#include<iostream.h>

class complex{private: float real, imag;

public: void getdata(); void outdata();

complex add (complex c2);};

complex complex:: add(complex c2)

{complex temp; temp.real = real + c2.real;

temp.imag = imag + c2. imag;

return temp;

} void main()

{complex c1, c2, c3;

c1.getdata(); c2.getdata();

c3 =c1.add(c2);

c1.outdata(); c2.outdata();

c3.outdata();}

Program

U4.10

11 of 83

Default Constructors

  • A constructor that does not accept any parameters is called default constructor. salesperson::salesperson() is the default constructor for class salesperson, since it does not take any parameters.
  • A default constructor supplied by the compiler does not do any thing special; it just initializes the data members with dummy values.
  • Note: If a class has no explicit constructor defined, the compiler will supply a default constructor, having no arguments.

U4.11

12 of 83

Declaration and definition

Code fragment defines a constructor inside the class definition:

class X { int i;

public:

int j, int k;

X() { i=j=k=0; //constructor

}

};

The simple constructor X::X() is as an inline member function here.

U4.12

13 of 83

Declaration and definition

Code fragment can also be defined for a constructor outside the class definition:

class X { int i;

public:

int j, k;

X(); // only declaration as a prototype

: // other members

};

X ::X() //constructor defined outside

{ i = j = k = 0;

}

U4.13

14 of 83

Need for Constructors

A structure or an array in c++ can be initialized at the time of their declaration. For example;

struct student { int rollno;

float marks;

};

int main()

{student s1= {0, 0.0};

}

But such initialization does not work for a class because class members have their associated access specifier. They might not be available to the outside world (outside their class). The following code snippet is invalid in C++.

U4.14

15 of 83

class student { private:

int rollno;

float marks;

public:

: // public members

};

int main()

{ student senior = { 0, 0.0}; // illegal ! Data members are not accessible.

:

:

};

The private data members are inaccessibe by a non-member function in main().

Need for Constructors

U4.15

16 of 83

Need for Constructors

  • There can be an alternative solution to it. If we define a member function (say init() inside a class to provide the initial values, as it is shown below:

class student { private:

int rollno; float marks;

public:

void init()

{ rollno = 0; marks=0.0; }

: //other public members

};

int main()

{ student senior ; // create an object

senior. init(); // initialize it

:

}

U4.16

17 of 83

Need for Constructors

  • Here the programmer has to explicitly invoke the function called init(), in order to initialise the object.
  • Thus the responsibility of initialization lies solely with the programmer . What if, the programmer fails to invoke init()? The object in such case is full of garbage and might cause havoc to your program.
  • Thus the responsibility of initialisation is taken away from the programmer and given to the compiler because the compiler exactly knows when objects are created.
  • Therefore every time an object is created , the compiler will automatically initialise it by invoking the initialisation function but if and only if the initialization function bears the same name as that of the class.
  • And, Obviously this function is known as a constructor.

U4.17

18 of 83

Copy Constructor

  • The copy constructor is a constructor which creates an object by initializing it with an object of the same class, which has been created previously. The copy constructor is used to:
  • Initialize one object from another of the same type.
  • Copy an object to pass it as an argument to a function.
  • Copy an object to return it from a function.
  • If a copy constructor is not defined in a class, the compiler itself defines one. If the class has pointer variables and has some dynamic memory allocations, then it is a must to have a copy constructor.
  • A copy constructor is a constructor of the form classname(classname &).

U4.18

19 of 83

Destructors

Whenever an object is created within a program, it also needs to be destroyed.

If a class has constructor to initialize members, it should also have a destructor to free up the used memory.

A destructor, as the name suggest, destroys the values of the object created by the constructor when the object goes out of scope.

A destructor is also a member function whose name is the same name as that of a class, but is preceded by tilde (‘~`).

For example, the destructor of class salesperson will be ~salesperson().

A destructor does not take any arguments nor does it return any value. The compiler automatically calls them when the objects are destroyed.

U4.19

20 of 83

Copy Constructor

The copy constructor is, however, defined in the class as a parameterized constructor receiving an object as argument passed by reference.

U4.20

21 of 83

Program for Copy Constructor

U4.21

22 of 83

Copy Constructor

  • In the above given class, two constructors have been used; a parameterized and a copy constructor sharing a common class name i.e. address. Thus, constructor can be overloaded.
  • It may be noted that the code for copy constructor has to be written by the programmer.
  • It may be further noted that the argument to a copy constructor has been passed by reference.
  • We can not pass the argument by value because this will result in copy calling itself on and on until the compiler runs out of memory.
  • Let us now write a program that uses this class to create an object called obj1 with some initial values. It also creates another object called obj2 and copies the contents of obj1 into obj2. It then displays the contents of obj2.

U4.22

23 of 83

Explanation

  • An object called obj1 of class address is created with some initial values. Another object obj2, a copy of obj1, is created with the help of the copy constructor.
  • At this stage, a question which arises is that, this job could have been done by simple assignment of objects i.e. obj1 = obj2, then why to use a copy constructor?
  • The need of a copy constructor is felt when the class includes pointers which need to be properly initialized. A simple assignment will fail to do this, because both the copies will hold pointers to same memory location.

U4.23

24 of 83

  • Shallow copy: when we don’t define our copy constructor and assignment operator, then compiler defines copy constructor and assignment operator for us and it provides a copying method known as a shallow copy ,also known as a member wise copy.��A shallow copy copies all of the member variable values. This works efficient if all the member variables are values, but may not work well if member variable point to dynamically allocated memory. The pointer will be copied but the memory it points to will not be copied, the variable in both the original object and the copy will then point to the same dynamically allocated memory, which is not usually what you want. The default copy constructor and assignment operator make shallow copies.

Deep & Shallow Coping

U4.24

25 of 83

  • Deep copy: A deep copy copies all member variables, and makes copies of dynamically allocated memory pointed to by the variables. To make a deep copy, we have to define our copy constructor and overload the assignment operator.��Requirements for deep copy in the class
  • A destructor is required to delete the dynamically allocated memory.

• A copy constructor is required to make a copy of the dynamically allocated memory.�• An overloaded assignment operator is required to make a copy of the dynamically allocated memory.

U4.25

26 of 83

#include <iostream.h>��void ConvertFToC(double f, double &c);�void ConvertFToC(float f, float &c);�void ConvertFToC(int f, int &c);�int main()

{�    double df, dc;�    float ff, fc;�    int i_f,i_c;    //if is a reserved word�    df = 75.0;�    ff = 75.0;�    i_f = 75;

U4.26

27 of 83

    // The compiler resolves the correct�    // version of ConvertFToC based on �    // the arguments in each call�    cout << "Calling ""double"" version" << endl;�    ConvertFToC(df,dc);�    cout << df << " == " << dc << endl << endl;��    cout << "Calling ""float"" version" << endl;�    ConvertFToC(ff,fc);�    cout << ff << " == " << fc << endl << endl;��    cout << "Calling ""int"" version" << endl;�    ConvertFToC(i_f,i_c);�    cout << i_f << " == " << i_c << endl << endl;

}

U4.27

28 of 83

void ConvertFToC(double f, double &c)�{�    cout << "In ""double"" version" << endl;�    c = (f - 32.0) * 5. / 9.;�}��void ConvertFToC(float f, float &c)�{�    cout << "In ""float"" version" << endl;�    c = (f - 32.0) * 5. / 9.;�}�void ConvertFToC(int f, int &c)�{�    cout << "In ""int"" version" << endl;�    c = (f - 32) * 5. / 9.;�}

U4.28

29 of 83

Operator Overloading

  • Extending capability of operators to operate on user defined data
  • Extends the semantics of an operator without changing its syntax
  • It's not possible to change an operator's precedence.
  • It's not possible to create new operators, eg ** which is used in some languages for exponentiation.
  • Commonly overloaded operators:
  • = (assignment operator)
  • + - * (binary operator)
  • += -= *= (compound assignment operators)
  • == != (comparison operators)

U4.29

30 of 83

Overloadable Operators

  • Allows almost all operators except
    • Member access (dot operator)
    • Scope resolution (::)
    • Conditional(?:)
    • Pointer to member(.*)
    • Size of Datatype (sizeof(…))
  • General format of overloading

Returntype operator operatorsymbol([arg1,[arg2]])

  • Can be defined operators as member function and friend function

U4.30

31 of 83

  • Overloading without explicit arguments to an operator function is known as unary operator overloading
  • overloading with a single explicit argument is known as binary operator overloading
  • With friend function, unary operators take one explicit argument and binary operators take two explicit arguments

U4.31

32 of 83

Binary Operator Over Loading

  • General syntax

Returntype operator operatorsymbol (arg )

{

// body of operator function

}

  • Binary overloaded operator function takes the first object as an implicit operand and the second operand must be passed explicitly

U4.32

33 of 83

  • Types:�There a three type of operators based on operands used, namely unary, binary, ternary.�Unary - This works with one operand (e.g: a++, a will be incremented by 1),�Binary - This works with two operands (e.g: a+b),�Ternary - This works with three operands (e.g: condition? value 1 : value 2).

U4.33

34 of 83

Unary Operators

  • Operators attached to a single operand (-a, +a, --a, a--, ++a, a++)
  • Example illustrates the overloading of unary operators
    • void operator ++ ( ) ;
    • void operator -- ( ) ;

  • Counter operator++()
  • {return Counter(++count);}

U4.34

35 of 83

Complement

  • The complement operator is used to find one’s complement of the numbers.
  • The symbol used for complement is ~
  • For example int y=0;
  • x=~y;
  • cout<<x;
  • The output will be 1

U4.35

36 of 83

What is ‘Friend’

  • Friend declarations introduce extra coupling between classes
    • Once an object is declared as a friend, it has access to all non-public members as if they were public
  • Access is unidirectional
    • If B is friend of A, B can access A’s non-public members; A cannot access B’s
  • A friend function of a class is defined outside of that class's scope
  • The major use of friends is
    • to provide more efficient access to data members than the function call
    • to accommodate operator functions with easy access to private data members
  • Friends have access to everything, which defeats data hiding, so use them carefully
  • Friends have permission to change the internal state from outside the class. Always recommend use member functions instead of friends to change state

U4.36

37 of 83

class Cents

{

private:  int m_nCents;

 public:

    Cents(int nCents) { m_nCents = nCents; }

    // Overload -cCents

    friend Cents operator-(const Cents &cCents);

};

// note: this function is not a member function!

Cents operator-(const Cents &cCents)

{    return Cents(-cCents.m_nCents);}

U4.37

38 of 83

  • Binary operators are operators that deal with two arguments, both generally being either variables or

constants. �Operator Use

  • + addition
  • - subtraction
  • * multiplication
  • / division
  • % remainder

= assignment

> boolean greater than < boolean less than

U4.38

39 of 83

Ternary Operator

  • Ternary operator is also known as conditional operator. It has three operands.
  • The operator is ?: .
  • Syntax: expr?stmt1:stmt2;
  • If the expression is true, then the statement1 will be executed.
  • Else statement2 will be executed.

U4.39

40 of 83

Unary Operator Overloading

// Program1.cpp: Index class with operator overloading for increment operator

 #include < iostream.h>

class Index

{

private:

int value; // Index Value

public:

Index ( ) // No argument constructor

{

value = 0;

}

int GetIndex( ) // Index Access

{ return value;

}

void operator + +( ) // prefix or postfix increment operator

{

value = value + 1; // value+ + ;

}

} ;

 

U4.40

41 of 83

Unary Operator Overloading

void main( )

{ Index idx1, idx2; // idex1 and idx2 are objects of Index class

 // display index values

cout << “ \nIndex1 = “ << idx1 . GetIndex ( ) ;

cout << “ \nIndex2 = “ << idx2 . GetIndex ( ) ;

 

// Advance Index objects with + + operators

+ + idx1; // equivalent to idx1. operator + + ( ) ;

idx2 + + ;

idx2 + + ;

cout << “ \ nIndex1 = “ << idx1. GetIndex ( ) ;

cout << “ \ nIndex2 = “ << idx2. GetIndex ( ) ;

}

 

RUN

 

Index1 = 0

Index2 = 0

Index1 = 1

Index2 = 2

 

 

U4.41

42 of 83

Unary operator using friend functions

Class test{

int x;

public:

test(){ x= 5;}

test(int a){ x= a;}

}

friend test operator++(test& ob);

};

test operator ++(test& ob) //passing an object by reference

{

ob.x++;

return (test(ob.x));};

U4.42

43 of 83

Example: Binary Operators

class BinaryExample

{

private:

int m_LocalInt;

public:

BinaryExample(int j)

{

m_LocalInt = j;

}

int operator+ (BinaryExample& rhsObj)

{

return (m_LocalInt + rhsObj.m_LocalInt);

}

};

U4.43

44 of 83

Example: Binary Operators (contd.)

void main()

{

BinaryExample object1(10), object2(20);

cout << object1 + object2; // overloaded operator called

}

U4.44

45 of 83

An operator function is created using the keyword operator. Operator functions can be either members or nonmembers of a class. Nonmember operator functions are almost always friend functions of the class.

A member operator function takes this general form:

ret-type class-name::operator#(arg-list)

{

// operations

}

U4.45

46 of 83

  • operator functions return an object of the class they operate on, but ret-type can be any valid type.
  • The # is a placeholder. When you create an operator function, substitute the operator for the #. For example, if you are overloading the / operator, use operator/. When you are overloading a unary operator, arg-list will be empty.
  • When you are overloading binary operators, arg-list will contain one parameter.

U4.46

47 of 83

#include <iostream>

using namespace std;

class loc {

int longitude, latitude;

public:

loc() {}

loc(int lg, int lt) {

longitude = lg;

latitude = lt;

}

void show() {

cout << longitude << " ";

cout << latitude << "\n";

}

loc operator+(loc op2);

};

// Overload + for loc.

loc loc::operator+(loc op2)

{

loc temp;

temp.longitude = op2.longitude + longitude;

temp.latitude = op2.latitude + latitude;

return temp;

}

int main()

{

loc ob1(10, 20), ob2( 5, 30);

ob1.show(); // displays 10 20

ob2.show(); // displays 5 30

ob1 = ob1 + ob2;

ob1.show(); // displays 15 50

return 0;

}

U4.47

48 of 83

operator+( ) has only one parameter even though it overloads the binary + operator. (You might expect two parameters corresponding to the two operands of a binary operator.) The reason that operator+( ) takes only one parameter is that the

operand on the left side of the + is passed implicitly to the function through the this pointer. The operand on the right is passed in the parameter op2.

The fact that the left operand is passed using this also implies one important point: When binary operators are overloaded, it is the object on the left that generates the call to the operator function.

ob1 = ob1 + ob2;

In order for the sum of ob1 and ob2 to be assigned to ob1, the outcome of that operation must be an object of type loc.

U4.48

49 of 83

It is important to understand that an operator function can return any type and that the type returned depends solely upon your specific application. It is just that, often, an operator function will return an object of the class upon which it operates.

EX-

class loc {

int longitude, latitude;

public:

loc() {} // needed to construct temporaries

loc(int lg, int lt) {

longitude = lg;

latitude = lt;

}

void show() {

cout << longitude << " ";

cout << latitude << "\n";

}

loc operator+(loc op2);

loc operator-(loc op2);

loc operator=(loc op2);

loc operator++();

};

U4.49

50 of 83

// Overload + for loc.

loc loc::operator+(loc op2)

{

loc temp;

temp.longitude = op2.longitude + longitude;

temp.latitude = op2.latitude + latitude;

return temp;

}

// Overload - for loc.

loc loc::operator-(loc op2)

{

loc temp;

// notice order of operands

temp.longitude = longitude - op2.longitude;

temp.latitude = latitude - op2.latitude;

return temp;

}

U4.50

51 of 83

// Overload asignment for loc.

loc loc::operator=(loc op2)

{

longitude = op2.longitude;

latitude = op2.latitude;

return *this; // i.e., return object that generated call

}

// Overload prefix ++ for loc.

loc loc::operator++()

{

longitude++;

latitude++;

return *this;

}

U4.51

52 of 83

int main()

{

loc ob1(10, 20), ob2( 5, 30), ob3(90, 90);

ob1.show();

ob2.show();

++ob1;

ob1.show(); // displays 11 21

ob2 = ++ob1;

ob1.show(); // displays 12 22

ob2.show(); // displays 12 22

ob1 = ob2 = ob3; // multiple assignment

ob1.show(); // displays 90 90

ob2.show(); // displays 90 90

return 0;

}

U4.52

53 of 83

In C++, if the = is not overloaded, a default assignment operation is created automatically for any class you define. The default assignment is simply a member- by-member, bitwise copy. By overloading the =, you can define explicitly what the assignment does relative to a class. In this example, the overloaded = does exactly the same thing as the default, but in other situations, it could perform other operations. Notice that the

operator=( ) function returns *this, which is the object that generated the call. This arrangement is necessary if you want to be able to use multiple assignment operations such as this:

ob1 = ob2 = ob3; // multiple assignment

look at the definition of operator++( ). As you can see, it takes no parameters. Since ++ is a unary operator, its only operand is implicitly passed by using the this pointer.

U4.53

54 of 83

Overloading the Shorthand Operators You can overload any of C++'s "shorthand" operators, such as +=, –=, and the like.For example, this function overloads += relative to loc:

loc loc::operator+=(loc op2)

{

longitude = op2.longitude + longitude;

latitude = op2.latitude + latitude;

return *this;

}

When overloading one of these operators, keep in mind that you are simply combining an assignment with another type of operation.

U4.54

55 of 83

Operator Overloading Using a Friend Function

You can overload an operator for a class by using a nonmember function, which is usually a friend of the class. Since a friend function is not a member of the class, it does not have a this pointer. Therefore, an overloaded friend operator function is passed the operands explicitly. This means that a friend function that overloads a binary operator has two parameters, and a friend function that overloads a unary operator has one

parameter. When overloading a binary operator using a friend function, the left operand is passed in the first parameter and the right operand is passed in the second parameter.

U4.55

56 of 83

class loc {

int longitude, latitude;

public:

loc() {} // needed to construct temporaries

loc(int lg, int lt) {

longitude = lg;

latitude = lt;

}

void show() {

cout << longitude << " ";

cout << latitude << "\n";

}

friend loc operator+(loc op1, loc op2); // now a friend

loc operator-(loc op2);

loc operator=(loc op2);

loc operator++();

};

U4.56

57 of 83

// Now, + is overloaded using friend function.

loc operator+(loc op1, loc op2)

{

loc temp;

temp.longitude = op1.longitude + op2.longitude;

temp.latitude = op1.latitude + op2.latitude;

return temp;

}

// Overload - for loc.

loc loc::operator-(loc op2)

{

loc temp;

// notice order of operands

temp.longitude = longitude - op2.longitude;

temp.latitude = latitude - op2.latitude;

return temp;

}

U4.57

58 of 83

// Overload assignment for loc.

loc loc::operator=(loc op2)

{

longitude = op2.longitude;

latitude = op2.latitude;

return *this; // i.e., return object that generated call

}

// Overload ++ for loc.

loc loc::operator++()

{

longitude++;

latitude++;

return *this;

}

U4.58

59 of 83

There are some restrictions that apply to friend operator functions. First, you may not overload the =, ( ), [ ], or –> operators by using a friend function. Second, as explained in the next section, when overloading the increment or decrement operators, you will need to use a reference parameter when using a friend function.

Using a Friend to Overload ++ or – –

If you want to use a friend function to overload the increment or decrement operators, you must pass the operand as a reference parameter. This is because friend functions do not have this pointers.

U4.59

60 of 83

#include <iostream>

using namespace std;

class loc {

int longitude, latitude;

public:

loc() {}

loc(int lg, int lt) {

longitude = lg;

latitude = lt;

}

void show() {

cout << longitude << " ";

cout << latitude << "\n";

}

loc operator=(loc op2);

friend loc operator++(loc &op);

friend loc operator--(loc &op);

};

// Overload assignment for loc.

loc loc::operator=(loc op2)

{

longitude = op2.longitude;

latitude = op2.latitude;

return *this; // i.e., return object that generated call

}

U4.60

61 of 83

// Now a friend; use a reference parameter.

loc operator++(loc &op)

{

op.longitude++;

op.latitude++;

return op;

}

// Make op-- a friend; use reference.

loc operator--(loc &op)

{

op.longitude--;

op.latitude--;

return op;

}

int main()

{

loc ob1(10, 20), ob2;

ob1.show();

++ob1;

ob1.show(); // displays 11 21

ob2 = ++ob1;

ob2.show(); // displays 12 22

--ob2;

ob2.show(); // displays 11 21

return 0;

}

U4.61

62 of 83

Binary Operator Overloading

  • Complex numbers consists of two parts: real part and imaginary part. It is represented as ( x+iy), where x is the real part and y is the imaginary part. The process of performing the addition operation is illustrated below. Let c1, c2and c3 be three complex numbers represented as follows:

  c1 = x1 + i y1; c2 = x2 + i y2;

 The operation c3 = c1 + c2 is given by

  c3 = ( c1 .x1 + c2 .x2 ) + i ( c1. y1 + c2. y2 ) ;

# include < iostream.h>

class complex

{ private : float real ; float imag ;

public : complex ( ) // no argument constructor

{ real = imag = 0 . 0 ; }

U4.62

63 of 83

Binary Operator Overloading

void getdata ( ) // read complex number

{ cout << “Real Part ? “ ; cin >> real ;

cout << “Imag Part ? “ ; cin >> imag ; }

complex operator + ( complex c2 ) ;

void outdata ( char *msg )

{ cout << endl << msg ; cout << “ ( “ << real ;

cout << “ , “ << imag<<“ ) “ ; }} ;

complex complex : : operator + ( complex c2 )

{ complex temp ; // object temp of complex class

temp . real = real + c2 . real ; //add real parts

temp . imag = imag = c2 . imag ; //add imaginary parts

return ( temp ) ;}

 

U4.63

64 of 83

Binary Operator Overloading

void main ( )

{

complex c1, c2 , c3 ; // c1 , c2 , c3 are object of complex class

cout << “ Enter Complex Number c1 . . “ << endl ;

cl . getdata ( ) ;

cout << “ Enter Complex Number c2 . . “ << endl ;

c2 . getdata ( ) ;

c3 = c1 + c2 ; // add c1 and c2 and assign the result to c3 i.e; c3 = c1 . operator+ ( c2 ) ;

c3 . outdata ( “ c3 = c1 + c2 : “ ) ; // display result

}

 RUN

 Enter Complex Number c1 . .

Real Part ? 2.5

Imag Part ? 2.0

Enter Complex Number c2 . .

Real Part ? 3.0

Imag Part ? 1.5

C3 = c1 + c2 : ( 5 . 5 , 3.5 )

U4.64

65 of 83

Operator Returns Values

 The operator function in the previous program Program1.cpp has a subtle defect. An attempt to use an expression such as;

idx1= idx2++;

will lead to a compilation error like Improper Assignment because the return type of operator++ is defined as void type. Such an assignment operation can be permitted after modifying the return type of the operator ++() member function of the index class.

#include < iostream.h>

class Index

{ private: int value; // Index Value

public: Index ( ) // No argument constructor

{ value = 0;}

int GetIndex( ) { return value;}

U4.65

66 of 83

Operator Returns Values

Index operator + +( ) // Returns nameless object of class Index

{ Index temp; // temp object

value = value + 1; // update index value

temp.value = value; // Initialise temp object

return temp; // Returns temp object

}} ;

 void main( ){ Index idx1, idx2;

cout << “ \nIndex1 = “ << idx1 . GetIndex ( ) ;

cout << “ \nIndex2 = “ << idx2 . GetIndex ( ) ;

idx1 = idx2++; idx2 + + ; // Returned object of idx2++ is unused

  cout << “ \ nIndex1 = “ << idx1. GetIndex ( ) ;

cout << “ \ nIndex2 = “ << idx2. GetIndex ( ) ;}

 

 

 

U4.66

67 of 83

Nameless Temporary Objects

A convenient way to return an object is to create a nameless object in the return statement itself.

#include < iostream.h>

class Index

{ private: int value; // Index Value

public: Index ( ) // No argument constructor

{ value = 0;}

int GetIndex( ) // Index Access

{ return value;}

Index operator + +( ) // Returns nameless object of class Index

{ value = value + 1; // update index value

return Index(value); }} ;

U4.67

68 of 83

Nameless Temporary Objects

 void main( )

{ Index idx1, idx2; // idx1 and idx2 are objects of Index class

cout << “ \nIndex1 = “ << idx1 . GetIndex ( ) ;

cout << “ \nIndex2 = “ << idx2 . GetIndex ( ) ;

// Returned object of idx2+ + is assigned to idx1

idx1 = idx2++; // invokes the overloaded function and assigned the return value to the object idx1 of the index

  idx2 + + ; // Returned object of idx2++ is unused

cout << “ \ nIndex1 = “ << idx1. GetIndex ( ) ;

cout << “ \ nIndex2 = “ << idx2. GetIndex ( ) ;

}

 

 

 

 

 

U4.68

69 of 83

Need For Virtual Functions

When objects of different class in a class hierarchy, react to the same message in their own unique ways, they are said to exhibit polymorphic behavior. In C++, a pointer to the base class can be used to point to its derived class objects.

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

 class Father // Father’s name

{ char name[20]; public:

  Father(char *fname)

{strcpy(name, fname); }

  void show() //show in base class

{cout<<”Father’s name:” << name << endl; }};

class son: public Father{ char name[20]; // Son’s name

public: void show(){}};

U4.69

70 of 83

Postfix Increment and Decrement Operators: ++ and –

  • C++ describes only the postfix increment and decrement operators.
  • The difference between the two is that in the postfix notation, the operator appears after postfix-expression, whereas in the prefix notation, the operator appears before expression.

i++;

  • The effect of applying the postfix increment operator (++) is that the operand's value is increased by one unit of the appropriate type. Similarly, the effect of applying the postfix decrement operator (––) is that the operand's value is decreased by one unit of the appropriate type.

U4.70

71 of 83

  • It is important to note that a postfix increment or decrement expression evaluates to the value of the expression prior to application of the respective operator. The increment or decrement operation occurs after the operand is evaluated.

expre_Postfix_Increment_and_Decrement_Operators.cpp

#include <iostream>

using namespace std;

int main() {

int i = 10;

cout << i++ << endl;

cout << i << endl;

}

U4.71

72 of 83

In the postfix form, the increment or decrement takes place after the value is used in expression evaluation, so the value of the expression is the same as the value of the operand. For example, the following program prints "++i = 6":

#include <iostream>

using namespace std;

int main() {

int i = 5;

cout << "++i = " << ++i << endl;

}

U4.72

73 of 83

Conclusion

  • Constructors are normally used to initialise variables and to allocate memory.
  • Similar to normal functions, constructors can be overloaded.
  • When an object is created and initialized at the same time, a copy constructor gets called.
  • C++ also provides destructor that destroys the objects when they are no longer required.
  • Allocation of memory objects to objects at the times of their construction is known as dynamic construction of objects with the help of new operator and can be deleted through delete operator.

U4.73

74 of 83

Summary

  • A class is a data type defined by the user where class describes the data and its behavior or functionality. It serves as a template to create objects.
  • The objects can be passed to as well as returned from functions. Inline, constant, nested, friend and static functions add new dimension to the flexibility of C++ program.
  • A constructor is a member function with the same name as that of its class and is used to initialise the objects of that class with a legal initial value.

U4.74

75 of 83

Summary

  • A constructor may be called explicitly as well as implicitly. It has various types depending on the basic demand of the program.
  • Objects can be initialized dynamically also with new operator. Make sure the memory allocated through new must be properly deleted through delete. Improper use of new and delete may lead to memory leak.
  • A destructor deinitializes an object before it goes out of scope and follows the same access rules of class members.

U4.75

76 of 83

Review Questions [Objective Types]

  1. How can we call member functions from outside the class?
  2. Point out the reasons why using new is a better idea than malloc()?
  3. What is the difference between the following two statements if a is pointer to an array allocated dynamically?

delete a;

delete [ ]a;

4. How can we initialize a const data members?

U4.76

77 of 83

Review Questions [Objective Types]

  1. What is an anonymous class?
  2. What is dangling pointer? Give example.
  3. Is it necessary to accept a reference in the copy constructor?
  4. Can a non-static member function access the static data?
  5. Can we use the renew operator in C++ to reallocate memory?
  6. Like other operators, can new operator also be overloaded?

U4.77

78 of 83

Review Questions [Short Answer Types]

  1. Design a class from which we can create objects by passing one, two or three arguments. The class should not have more than constructor function.
  2. How can we initialize an array of objects?
  3. Can we initiate an object s of class sample through a statement like sample s = 10; ?
  4. Write a snippet to show memory leak in C++?
  5. What is the size of an object of an empty class? And Why?
  6. Does the delete operator call the destructor of the class?

U4.78

79 of 83

Review Questions [Short Answer Types]

  1. How can one return an error value from the constructor?
  2. The this pointer always contain the address of the object using which the member function is being called. Illustrate the concept with the help of an object.
  3. Can we modify the this pointer?
  4. Discus the various situations when a copy constructor is automatically invoked.

U4.79

80 of 83

Review Questions [Long Answer Types]

1. Write a program using a class to store marks list of 15 students and to print the highest marks as well as the average of all marks.

  1. Illustrate the scope rules of global class, global object, local class and local object through some code fragment in C++.
  2. How nesting of member functions work in a class? Discuss.
  3. When declaration of static member and static functions become necessary ? Give example.

U4.80

81 of 83

Review Questions [Long Answer Types]

  1. What should we keep in mind before the objects of an inner class can be declared? Show the validity of your remark in the perspective of a Nested class program.
  2. How the working of inline function is different from other functions? Is it also different from #define value replacement directive or macro concept?
  3. Define a situation that requires a function to operate on objects of two different classes. Write a program to signify the friend function as bridge.

U4.81

82 of 83

Review Questions [Long Answer Types]

  1. Write a program to maintain a bank account class where you can pass objects as parameters to functions.
  2. Write the syntax for creating nameless objects and how they will be destroyed in a program?
  3. Create a vector class where array can be dynamically allocated?

U4.82

83 of 83

Recommended Books

TEXT:

1. A..R.Venugopal, Rajkumar, T. Ravishanker “Mastering C++”, TMH, 2009.

2. S. B. Lippman & J. Lajoie, “C++ Primer”, 6th Edition, Addison Wesley, 2006.

REFERENCE:

1. R. Lafore, “Object Oriented Programming using C++”, Galgotia Publications, 2008.

2. D . Parasons, “Object Oriented Programming with C++”, BPB Publication.

3. Steven C. Lawlor, “The Art of Programming Computer Science with C++”, Vikas Publication.

4. Schildt Herbert, “C++: The Complete Reference”, 7th Ed., Tata McGraw Hill, 2008.

U4.83