76
1 Course Name- B Sc IT Subject Name - C++ Semester - II Neetu Gupta

106da session5 c++

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: 106da session5 c++

1

Course Name- B Sc IT

Subject Name - C++

Semester - II

Neetu Gupta

Page 2: 106da session5 c++

Contents

• Copy constructorFriend functions

• References data members

• Pointer data members

• Call by value

• Call by reference

Page 3: 106da session5 c++

Contents

• Function Template Definition• Function Template Instantiation• Class Template Definition• Class Template Instantiation• Non-type Parameters• Class Template Specialization• Class Template Members• Class Template Friends• Derived Class Templates

Page 4: 106da session5 c++

Copy Constructor

Copy constructor is• a constructor function with the same name as the class • used to make deep copy of objects.

• If a copy constructor is not defined in a class, the compiler itself defines one. This will ensure a shallow copy. If the class does not have pointer variables with dynamically allocated memory, then one need not worry about defining a copy constructor. It can be left to the compiler's discretion.

• But if the class has pointer variables and has some dynamic memory allocations, then it is a must to have a copy constructor.

Page 5: 106da session5 c++

There are 3 important places where a copy constructor is called.

• When an object is created from another object of the same type

A a1;

A a2 = a1;

• When an object is passed by value as a parameter to a function

• When an object is returned from a function

Page 6: 106da session5 c++

• For any class, the syntax for copy constructor will be like

class-name (const class-name &b)

1. Name of copy constructor is same as class name like any other constructor

2. The argument is of the class type itself.

3. The argument must be sent by reference

4. The argument must be sent as a constant value

Page 7: 106da session5 c++

class B    //With copy constructor{

          private:          char *name;

           public:         B()           {

           name = new char[20];           }           ~B()           {

           delete name[];           }

     //Copy constructor

         B (const B &b)           {

         name = new char[20];strcpy (name, b.name);          

}};

Page 8: 106da session5 c++

• Let us Imagine if you don't have a copy constructor for the class B.

• At the first place, if an object is created from some existing object, we cannot be sure that the memory is allocated.

• Also, if the memory is deleted in destructor, the delete operator might be called twice for the same memory location. This is a major risk.

• One happy thing is, if the class is not so complex this will come to the fore during development itself. But if the class is very complicated, then these kind of errors will be difficult to track.

Page 9: 106da session5 c++

• We can make use of this in a main() function as

main() {B b1;B b2 = b1;

}• Here, b2 is created from object b1 with the call of copy

constructor.• Hence the memory allocated to variable name will be

different for both the objects as we are doing so in copy constructor

• If we have not done so, then both the objects b1 and b2 would be pointing to same memory location which might lead to disasters in the program.

Page 10: 106da session5 c++

References

• C++ references allow you to create a second name for the a variable that you can use to read or modify the original data stored in that variable.

• This means that when you declare a reference and assign it a variable, it will allow you to treat the reference exactly as though it were the original variable for the purpose of accessing and modifying the value of the original variable--even if the second name (the reference) is located within a different scope. (important)

Page 11: 106da session5 c++

• This means, for instance, that if you make your function arguments references, and you will effectively have a way to change the original data passed into the function.

• It allows you to dramatically reduce the amount of copying that takes place behind the scenes, when we pass a argument by value in a function

Page 12: 106da session5 c++

Reference - Syntax

• Declaring a variable as a reference rather than a normal variable simply entails appending an ampersand to the type name, such as this "reference to an int"

int& foo = <variable-name>; • When a reference is created, you must tell it which variable

it will become an alias for or store the reference of.• After you create the reference foo, whenever you use the

variable, you can just treat it as though it were a regular integer variable. But when you create it, you must initialize it with another variable, whose address it will keep around behind the scenes to allow you to use it to modify that variable.

Page 13: 106da session5 c++

• In a way, this is similar to having a pointer that always points to the same thing.

• One key difference is that references do not require dereferencing in the same way that pointers do; you just treat them as normal variables.

• A second difference is that when you create a reference to a variable, you need not do anything special to get the memory address. The compiler figures this out for you

Page 14: 106da session5 c++

• A simple code could be asint x;

// foo is now a reference to x

int& foo = x;

// foo and x are same so

// if you change foo, it will set x to 56

foo = 56;

cout << x <<endl;

Here output will be

56

Page 15: 106da session5 c++

Functions taking References Parameters

• A parameter that we specify in function declaration can be a reference too.

• That means when we change the value of reference in the function, the value of actual argument will also get changed.

• This we call as pass-by-refrence. An important feature of C++.

Page 16: 106da session5 c++

• Here's a simple example of setting up a function to take an argument "by reference", implementing the swap function: void swap (int& first, int& second) {

int temp = first; first = second; second = temp;

}

• Here first and second are passed by reference. When we change the value of first and second then the changes will be reflected in the original arguments also.

Page 17: 106da session5 c++

int main () {int a = 2; int b = 3; swap( a, b ); // call to swap functionreturn 0;

}

• After the call of swap function a will be 3 and b will be 2.• Because a is passed to first and b is passed to second

in function swap. • Both are references. When we change first and second

in swap, a and b are also changed.

Page 18: 106da session5 c++

References as class members

• You can store members by reference if they are guaranteed to exist elsewhere.

• Reference member variables are used when the object they refer to exists outside of the scope of the class in question, and the same one is guaranteed to exist for the duration of the lifetime of your class' objects.

• A reference to the original is passed in as a parameter to the constructor and the reference member is initialized in the constructor's initialization list.

Page 19: 106da session5 c++

class A {}

class B {public:     

A& a;     // Reference to class type Aint x;

B(A& extr) :a(extr){ }

};

Here B is a class which hasone member variable a which is reference of type class Asecond member variable, a normal variable of int type.

Page 20: 106da session5 c++

void main() {     A ref;     B b(ref) ;     b.x=9; 

}Here we create an object ref of type A.• We send it to constructor of B, where it gets

initialized to a member of class B.• Since a is reference, the objects ref and a are

pointing to same object and not to two different objects.

Page 21: 106da session5 c++

Initializing reference members

• As we have already studied that a reference should always be initialized with a variable when it is declared.

• Hence, if we have a member variable declared as reference it must be initialized in the initialization list always otherwise compiler will give an error.

Page 22: 106da session5 c++

//class B {

public:     A& a;     // Reference to class type Aint x;

B(A& extr) :a(extr) // initialized in initialization list{

a = extr; // compiler Error;}

};

• If we try to assign a value to a reference in the constructor it will an error, as shown above.

• Because giving reference a value in constructor is assignment not initialization.

• It should always be done in the initialization list.

Page 23: 106da session5 c++

Pointers as data members

• Like normal variables, we can always have data members which are pointers to a data type.

class A {

int* iptr;

}• Here, the iptr is a pointer to int and not a simple

int type variable.• We should take special care when we have

pointer data members

Page 24: 106da session5 c++

• A pointer data member should be properly allocated and deallocated memory in the constructor and destructor of the class.

• Every class that has a pointer data member should include the following member functions: – a destructor, – a copy constructor, – operator= (assignment)

Page 25: 106da session5 c++

• Lets take an exampleclass Test    //With copy constructor{

          private:          char *name;

           public:         Test()           {

           name = new char[20];           }           ~ Test()           {

           delete name[];           }     

};

Page 26: 106da session5 c++

• Class test, has a data member name which is a pointer to char type.

• We must be careful to alocate memory in constructor for this using new operator.

• Similarly when the object is destroyed, destructor will be called. We should be careful to deallocate the memory that is allocated in constructor using delete operator.

Page 27: 106da session5 c++

Call by value vs. call by reference

• When we write a function likef ( int x ) {

cout >> “ value of X in f() before change : “ >> x;x =3;cout >> “ value of X in f() before change : “ >> x;

}Here x is passed by value that means if we change

the value of x in f(), there will be no effect on the value of argument that is sent at the time of f() call.

This is called as pass-by-value

Page 28: 106da session5 c++

• If we call function f() in main asmain() {

int i =10;cout >> “ value of I before calling f() : “ >> I;f(i);cout >> “ value of I after calling f() : “ >> I;

}

Output will be :value of I before calling f() : 10value of X in f() before change : 10value of X in f() before change : 3value of I after calling f() : 10

Page 29: 106da session5 c++

• The value of i is set to 10 that is what is printed.• When we pass I to f(), its value is set to X so X is

10.• Later we change X to 3, that is what is printed.• The control comes back to main after calling f(),

the I is still 10.• Though we changed the value of parameter X in

f(), but the changes are not reflected in i.• This is because X is passed by value.

Page 30: 106da session5 c++

• Pass by referenceWhen we write a function like

f ( int& x ) {cout >> “ value of X in f() before change : “ >> x;

x =3;cout >> “ value of X in f() before change : “ >> x;

}• Here x is passed by reference and not by value

that means if we change the value of x in f(), there will be change in the value of argument that is sent at the time of f() call. This is called as pass-by-reference

Page 31: 106da session5 c++

• If we call function f() in main asmain() {

int i =10;cout >> “ value of I before calling f() : “ >> I;f(i);cout >> “ value of I after calling f() : “ >> I;

}

Output will be :value of I before calling f() : 10value of X in f() before change : 10value of X in f() before change : 3value of I after calling f() : 3

Page 32: 106da session5 c++

• The value of i is set to 10 that is what is printed.• When we pass I to f(), its value is set to X so X is

10.• Later we change X to 3, that is what is printed.• The control comes back to main after calling f(),

the I is 3 now.• We changed the value of parameter X in f(), the

changes are now reflected in i.• This is because X is passed by reference.

Page 33: 106da session5 c++

Templates

• Templates are used to write down generaic code.

• When we need to write a common code for different data type basic or class type we can do so with the help of templates.

• In c++, we will study 2 types1. Function templates

2. class templates

Page 34: 106da session5 c++

Function Templates

• Function templates are special functions that can operate with generic types.

• This allows us to create a function template whose functionality can be adapted to more than one type or class without repeating the entire code for each type.

• In C++ this can be achieved using template parameters.

Page 35: 106da session5 c++

Template parameter

• A template parameter is a special kind of parameter that can be used to pass a type as argument.

• As regular function parameters can be used to pass values to a function, template parameters allow to pass also types to a function.

• These function templates can use these parameters as if they were any other regular type to write a code for generic data type or class.

Page 36: 106da session5 c++

Function template syntax

• The format for declaring function templates with type parameters is:

template <class identifier> function_declaration;template <typename identifier> function_declaration;

• The only difference between both prototypes is the use of either the keyword class or the keyword typename.

• Its use is indistinct, since both expressions have exactly the same meaning and behave exactly the same way.

Page 37: 106da session5 c++

• For example, to create a template function that returns the greater one of two objects we could use:

template <class myType> myType GetMax (myType a, myType b) {

return (a>b?a:b); }

• Here we have created a template function with myType as its template parameter.

• This template parameter represents a type that has not yet been specified, but that can be used in the template function as if it were a regular type.

• As you can see, the function template GetMax returns the greater of two parameters of this still-undefined type.

Page 38: 106da session5 c++

Function template - Use

• To use this function template we use the following format for the function call:

function_name <type> (parameters);

• For example, to call GetMax to compare two integer values of type int we can write:

int x,y; GetMax <int> (x,y);

Page 39: 106da session5 c++

• When the compiler encounters this call to a template function like,

GetMax <int> (x,y);

it uses the template to automatically generate a function replacing each appearance of myType by the type passed as the actual template parameter (int in this case) and then calls it.

• This process is automatically performed by the compiler and is invisible to the programmer.

Page 40: 106da session5 c++

// function template #include <iostream> using namespace std; template <class T> T GetMax (T a, T b) {

T result; result = (a>b)? a : b; return (result);

}

int main () { int i=5, j=6, k; long l=10, m=5, n; k=GetMax<int>(i,j); // create a function for int typen=GetMax<long>(l,m); // create a function for long typecout << k << endl; cout << n << endl; return 0;

}

Output is6 10

Page 41: 106da session5 c++

• In this case, we have used T as the template parameter name instead of myType because it is shorter and in fact is a very common template parameter name.

• In the example above we used the function template GetMax() twice.

• The first time with arguments of type int and the second one with arguments of type long.

• The compiler has instantiated and then called each time the appropriate version of the function.

Page 42: 106da session5 c++

• As you can see, the type T is used within the GetMax() template function even to declare new objects of that type:

  T result;

• Therefore, result will be an object of the same type as the parameters a and b when the function template is instantiated with a specific type.

Page 43: 106da session5 c++

• Our template function includes only one template parameter (class T) and the function template itself accepts two parameters, both of this T type.

• We cannot call our function template with two objects of different types as arguments:

int i; long l; k = GetMax (i,l);

• This would not be correct, since our GetMax function template expects two arguments of the same type, and in this call to it we use objects of two different types.

Page 44: 106da session5 c++

More than one type parameter

• We can also define function templates that accept more than one type parameter, simply by specifying more template parameters between the angle brackets.

• For example:template <class T, class U> T GetMin (T a, U b) {

return (a<b ? a :b); }

In this case, our function template GetMin() accepts two parameters of different types and returns an object of the same type as the first parameter (T) that is passed.

Page 45: 106da session5 c++

• For example, after that declaration we could call GetMin() with:

int I, j;

long l; i = GetMin<int, long> (j, l);

or simply:i = GetMin (j, l);

Here even though j and l have different types, since the compiler can determine the appropriate instantiation anyway.

Page 46: 106da session5 c++

Class Template• We also have the possibility to write class templates, so that a class

can have members that use template parameters as types.

• For exampletemplate <class T> class mypair {

T values [2]; public:

mypair (T first, T second) { values[0]=first;

values[1]=second; }

};

Page 47: 106da session5 c++

• We can define a class Template as

For exampletemplate <class T> class mypair {

T values [2]; public:

mypair (T first, T second) { values[0]=first;

values[1]=second; }

};

• The class that we have just defined serves to store two elements of any valid type.

Class Template definition

Page 48: 106da session5 c++

• For example, if we wanted to declare an object of this class to store two integer values of type int with the values 115 and 36 we would write:

  mypair<int> myobject (115, 36);

• The same class would also be used to create an object to store any other type:

  mypair<double> myfloats (3.0, 2.18);

Page 49: 106da session5 c++

• The only member function in the previous class template has been defined inline within the class declaration itself.

• In case that we define a function member outside the declaration of the class template, we must always precede that definition with the template <...> prefix as:

template <class T> T mypair<T>::getmax ()

Page 50: 106da session5 c++

// class templates #include <iostream> using namespace std; template <class T> class mypair {

private:T a, b;

public: mypair (T first, T second) {

a=first; b=second;} T getmax ();

};

template <class T> T mypair<T>::getmax () {

T retval; retval = a>b? a : b; return retval;

}

Page 51: 106da session5 c++

• In the example, mypair is the class that stores two template type variables.

• It also has a function getMax(), that find out the maximum of two numbers the object of class stores.

Page 52: 106da session5 c++

• The compiler will generate the complete code of the class for each type, when we declare an object of the class myPair specifying a type of T.

• For exampleint main () {

mypair <int> myobject (100, 75);cout << myobject.getmax(); return 0;

}

• In this example, a complete class is created with T as int, because we are using mypair <int>. This we can call instantiation of class template.

Class Template Instantiation

Page 53: 106da session5 c++

Template specialization

• At times we want to define a different implementation for a template when a specific type is passed as template parameter

• We can always declare a specialization of that template for that particular data type as the need be.

Page 54: 106da session5 c++

• This is the syntax used in the class template specialization:

template <> class mycontainer <char> {

... };

• Notice that we precede the class template name with an empty template<> parameter list. This is to explicitly declare it as a template specialization.

Page 55: 106da session5 c++

• For example, let's suppose that we have a very simple class called mycontainer that can have the members as1. one element of any type and 2. it has just one member function called increase,

which increases its value. 3. But we find that when it stores an element of type

char it would be more convenient to have a completely different implementation with a function member uppercase,

4. so we decide to declare a class template specialization for type char only.

Page 56: 106da session5 c++

// template specialization #include <iostream> using namespace std;

// class template: template <class T> class mycontainer {

T element; public:

mycontainer (T arg) {element=arg;

}

T increase () {return ++element;

} };

Page 57: 106da session5 c++

// class template specialization for char type will be as: template <> class mycontainer <char> {

char element; public:

mycontainer (char arg) {element=arg;

} char uppercase () {

if ((element>='a')&&(element<='z')) element+='A'-'a';

return element; }

};

Page 58: 106da session5 c++

Carefully see the code usedtemplate <>

• This is to explicitly declare it as a template specialization.

class mycontainer <char> { ... };

• Here <char> is the specialization parameter after the class template name. This specialization parameter itself identifies the type for which we are going to declare a template class specialization i.e. char.

Page 59: 106da session5 c++

• Notice the differences between the generic class template and the specialization:

template <class T> class mycontainer { ... }; template <> class mycontainer <char> { ... };

Here first line is the generic template,second one is the template specialization.

Remember• When we declare specializations for a template class, we

must also define all its members, even those exactly equal to the generic template class, because there is no "inheritance" of members from the generic template to the specialization.

Page 60: 106da session5 c++

•Besides the template arguments that are preceded by the class or typename keywords , which represent types, templates can also have regular typed parameters, similar to those found in functions.Like we can a particular type specified like int, float, or any class-type as well as

template <class T, int N> Here T is template type where as second parameter is fixed i.e. int here.

60

Non-type parameters for templates

Page 61: 106da session5 c++

// sequence template // this class template that is used to contain sequences of elements

#include <iostream> using namespace std;

template <class T, int N> class mysequence {

T memblock [N]; public:

void setmember (int x, T value); T getmember (int x);

};

template <class T, int N> void mysequence<T,N>::setmember (int x, T value) {

memblock[x]=value; }

template <class T, int N> T mysequence<T,N>::getmember (int x) {

return memblock[x]; }

61

Page 62: 106da session5 c++

•In the class mysequence we have two arguments for template;

first is template typename that will vary when we create an object of this class

second is specific i.e. int and when we create an object we will use this as

mysequence <double, 5> mydoubles;

double replaces T5 is the value for parameter N

62

Page 63: 106da session5 c++

int main () { mysequence <int,5> myints; mysequence <double,5> myfloats;

myints.setmember (0,100); myfloats.setmember (3,3.1416); cout << myints.getmember(0) << '\n'; cout << myfloats.getmember(3) << '\n'; return 0;

}

63

Page 64: 106da session5 c++

It is also possible to set default values or types for class template parameters.

For example, if the previous class template definition had been:

template <class T=char, int N=10> class mysequence {..};

We could create objects using the default template parameters by declaring:

  mysequence<> myseq;

This would be same as

mysequence<char,10> myseq

64

Page 65: 106da session5 c++

Default values for class template parameters

• It is also possible to set default values or types for class template parameters.

For example, if the previous class template definition had been:

template <class T=char, int N=10> class mysequence {..};

We could create objects using the default template parameters by declaring:

  mysequence<> myseq;

This would be same as

mysequence<char,10> myseq

Page 66: 106da session5 c++

Friends functions

• In principle, private and protected members of a class cannot be accessed from outside the same class in which they are declared.

• However, this rule does not affect friends.

• Friends are functions or classes declared with the friend keyword.

Page 67: 106da session5 c++

• we can declare an external function as friend of a class

• This allows this function to have access to the private and protected members of this class.

• For this 1. We should declare a prototype of this

external function within the class,

2. and preceding it with the keyword friend

Page 68: 106da session5 c++

• Suppose we want to declare an external function in our program, that create a copy of CRectangle class.

• This function should be likeCRectangle duplicate (CRectangle rectparam) {

CRectangle rectres; rectres.width = rectparam.width*2; rectres.height = rectparam.height*2;return (rectres);

}• But if we define this function outside class, we can not access width

and height members of class CRectangle here as they are protected or private.

• For this we declare this function as friend to class CRectangle

Page 69: 106da session5 c++

// friend functions #include <iostream> using namespace std; class CRectangle {

int width, height; public:

void set_values (int, int); int area () {

return (width * height);} friend CRectangle duplicate (CRectangle); // friend function declaration in class

};

void CRectangle::set_values (int a, int b) { width = a; height = b;

}

CRectangle duplicate (CRectangle rectparam) { CRectangle rectres; rectres.width = rectparam.width*2; rectres.height = rectparam.height*2; return (rectres);

}

Page 70: 106da session5 c++

• It can be used as

int main () { CRectangle rect, rectb; rect.set_values (2,3); rectb = duplicate (rect); cout << rectb.area(); return 0;

}

• The duplicate function is a friend of CRectangle. From within that function we have been able to access the members width and height of different objects of type CRectangle, which are private members.

• Notice that neither in the declaration of duplicate() nor in its later use in main() have we considered duplicate a member of class CRectangle.

Page 71: 106da session5 c++

Friend classes

• As we have the possibility to define a friend function, we can also define a class as friend of another class

• We can do so by granting that first class access to the protected and private members of the second class.

• This can be done by declaring first class as a friend of other class.

Page 72: 106da session5 c++

Friend class - syntax

• We can do this as

class A {

public:

friend class B;

}

• Here class B is friend of class A that means class B can access the all private and protected members of class A.

Page 73: 106da session5 c++

Example:• Suppose we want to have declared CRectangle

as a friend of CSquare so that CRectangle member functions could have access to the protected and private members of CSquare, more concretely to CSquare::side, which describes the side width of the square.

• This is necessary because within the declaration of CRectangle we want to add a function convert() that will change an object of type CSquare to CRectangle.

Page 74: 106da session5 c++

// friend class #include <iostream> using namespace std; class CSquare; class CRectangle {

private : int width, height;

public: int area () {return (width * height);} void convert (CSquare a);

};

class CSquare { private:

int side; public:

void set_side (int a) {side=a;} friend class CRectangle; // declares CRectangle as the friend class of

CSquare};

void CRectangle::convert (CSquare a) { width = a.side; // accessing private member of CSquare classheight = a.side;

}

Page 75: 106da session5 c++

• Now we can easily covert a CSquare class into CRectangle as

int main () { CSquare sqr; CRectangle rect; sqr.set_side(4); rect.convert(sqr); // conversioncout << rect.area(); return 0;

}Output is:

16

Page 76: 106da session5 c++

Thank You

76