3d7b7 session4 c++

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

Transcript of 3d7b7 session4 c++

Page 1: 3d7b7 session4 c++

1

Course Name- B Sc IT

Subject Name - C++

Semester - II

Neetu Gupta

Page 2: 3d7b7 session4 c++

Contents

• Function overloading

• Operator overloading

• Inheritance

• Different forms of inheritance

• Constructors and

• Destructors in inheritance

• Virtual base class

Page 3: 3d7b7 session4 c++

Contents

• Virtual base class

• Pointer to base class

• Dynamic polymorphism

• Virtual functions

• Type conversions

Page 4: 3d7b7 session4 c++

Function overloading

• In C we can have only one function with a given name.

• But, in C++ we have a feature to declare more than one function with the same name as long as they have different signatures i.e. parameters.

• The difference in parameters could be either in number or type or both.

Page 5: 3d7b7 session4 c++

• Function overloading is the practice of declaring the same function with different signatures.

• The same function name will be used with different number of parameters and parameters of different type. But overloading of functions with different return types are not allowed.

• You overload a function name f by declaring more than one function with the name f in the same scope. The declarations of f must differ from each other by the types and/or the number of arguments in the argument list.

Page 6: 3d7b7 session4 c++

• For examples we can have following functions in a c++ program

void Add(int x, int y){        cout<<" Integer addition result: "<<(x+y);}

void Add(double x, double y) {

cout<< " Double addition result: "<<(x+y);}

    void Add(float x, float y) {

cout<< " float addition result: "<<(x+y);    }

Three functions with same name i.e. Add(..) but differ in types

Page 7: 3d7b7 session4 c++

Calling an overloaded function

• When we call an overloaded function, the correct function is selected by comparing the argument list of the function call with the parameter list of each of the overloaded functions.

• The function i.e. actually called depends upon the arguments we pass at the time of function call statement.

• This is an example of static polymorphism

Page 8: 3d7b7 session4 c++

int main() { Add (10,10); Add (10.10d, 10.5d); Add (10.10f, 10.5f);

}1. Add (10,10); calls the function void Add (int x,

int y)2. Add (10.10d, 10.5d); calls the function void

Add (double x, double y) 3. Add (10.10f, 10.5f); calls the function void Add

(float x, float y)

Page 9: 3d7b7 session4 c++

• Remember function overloaded can not be done on the basis of return type.

• For example following functions will give error, as both the functions are same as they only differ in return type:

void Add(int x, int y)

int Add(int x, int y)

Page 10: 3d7b7 session4 c++

Operator overloading

• C++ CVectororporates the option to use standard operators to perform operations with classes in addition to with fundamental types.

For example, int a, b, c; a = b + c;

• This is obviously valid code in C++, sCVectore the different variables of the addition are all fundamental types.

Page 11: 3d7b7 session4 c++

• But if we have a code like• class Product {

string name; float price;

};

Product prod1, prod2, prod3;

prod3 = prod1 + prod2; // Compilation error

• The above code will not work, as the compiler does not on how to apply + on Product type variables i.e. prod1 and prod2 here.

Page 12: 3d7b7 session4 c++

• Using C++ feature to overload operators, we can design classes able to perform operations using standard operators.

• Here is a list of all the operators that can be overloaded:

+ - * / = < > += -= *= /= << >> <<= >>= == != <= >= ++ -- % & ^ ! | ~ &= ^= |= && || %= [] () , -> * -> new delete new[] delete[]

Page 13: 3d7b7 session4 c++

• To overload an operator in order to use it with classes we declare operator functions, which are regular functions whose names are the operator keyword followed by the operator sign that we want to overload.

• The format is will be as:

type operator sign (parameters) { /*...*/

}

Page 14: 3d7b7 session4 c++

• Example#CVectorlude <iostream> using namespace std; class CVector {

public: int x, y; CVector () {}; // default constructorCVector (int,int); // constructorCVector operator + (CVector); // + operator overloaded

};

CVector: CVector (int a, int b) { x = a; y = b;

}

CVector CVector::operator+ (CVector param) { CVector temp; temp.x = x + param.x; temp.y = y + param.y; return (temp);

}

Page 15: 3d7b7 session4 c++

Here you have an example that overloads the

addition operator (+). • We are going to create a class to store

bidimensional vectors • X represents x-coordinate and y represents y-

coordinate value for a CVector.• The addition of two bidimensional vectors is an

operation as simple as adding the two x coordinates to obtain the resulting x coordinate and adding the two y coordinates to obtain the resulting y.

Page 16: 3d7b7 session4 c++

• Now see how can we use the class CVector as

int main () {

CVector a (3,1);

CVector b (1,2);

CVector c;

c = a + b;

cout << c.x << "," << c.y;

return 0;

}

Page 17: 3d7b7 session4 c++

• Notice the below two methodsCVector (int, int); // function name CVector (constructor)

CVector operator+ (CVector); // function returns a CVector

• The function operator+ of class CVector is the one that is in charge of overloading the addition operator (+).

• This function of class CVector can be called either implicitly using the operator, or explicitly using the function name

Page 18: 3d7b7 session4 c++

c = a + b; // using the operator

c = a.operator+ (b); // using the function name

• Both these expressions are equivalent and will call the +operator function defined in class CVector.

• This way we can overload any binary operator in c++ like - , /, % etc.

Page 19: 3d7b7 session4 c++

Unary operator overloading

We can overload unary operator using two ways as

• with either a nonstatic member function that has no parameters

return_type operator@()• Or with a nonmember function that has one

parameter return_type operator@(T)

Here, @ could be any unary opeartor and T is a type.return_type could be any type

Page 20: 3d7b7 session4 c++

Add the following function to class CVector declared beforeCVector CVector::operator! () {

CVector temp; temp.x = !x; temp.y = !y; return (temp);

}

Here operator ! Is overloaded and define a behavior for class CVector.

Page 21: 3d7b7 session4 c++

The above code can be use in main() function as

int main() {

CVector ox(10,30); CVector oy = !ox // function operator! Is called

}

Page 22: 3d7b7 session4 c++

• Overloading decrement (--) and CVectorrement(++) operators is different

• SCVectore ++ and – have different meanings for postfix and prefix we should override both forms.

• For this we should add two set of functions like

// Operator Function Definition for prefix

type operator ++ ();type operator -- ();

Page 23: 3d7b7 session4 c++

// Operator Function Definition for postfix type operator ++ (int);type operator -- (int);

Here we make use of a dummy argument.

• As you can see in this case we use int as a dummy argument for post-fix, when we redefine the functions for the unary CVectorrement (++) and decrement (--) overloaded operators.

• You must remember that int isn't an integer, but just a dummy argument. You can see it as a signal to the compiler to create the post-fix notation of the operator.

Page 24: 3d7b7 session4 c++

• Two functions for ++ operator in class CVector could be as below:

CVector operator ++ () {

// Operator Function Definition for prefix

return CVector (++x, ++y);

}

CVector operator ++ (int) {

// Operator Function Definition with dummy //argument for postfix

return CVector (x++, y++);

}

Page 25: 3d7b7 session4 c++

• Similarly, Two functions for -- operator in class CVector could be as below:

CVector operator -- () {

// Operator Function Definition for prefix

return CVector(--x, --y);

}

CVector operator -- (int) {

// Operator Function Definition with dummy //argument for postfix

return CVector (x--, y--);

}

Page 26: 3d7b7 session4 c++

Remember

• In operator overloading always remember:

1. We can not change the precedence and associatively of operators even if we overload them in a class.

2. Few operators can not be overloaded like :1. scope resolution operator - ::

2. sizeof operator

3. Conditional operator (?:)

4. class member access operators (.,.*)

Page 27: 3d7b7 session4 c++

Type conversion

• Type Conversion is the process of converting one type into another.

• In other words converting an expression of a given type into another is called type casting or conversion

• There are two ways 1. Automatic Conversion otherwise called as

Implicit Conversion2. Type casting otherwise called as Explicit

Conversion

Page 28: 3d7b7 session4 c++

Implicit Type Conversion

• This is automatic conversion, which is not done using any operator or function.

• The value gets automatically converted to the specific type in which it is assigned.

• Looking at the expression, the compiler automatically converts an expression of one type into another type

Page 29: 3d7b7 session4 c++

• For example#include <iostream.h>void main(){

short x=6000;int y;y=x;

}

• In the above example the data type short namely variable x is converted to int and is assigned to the integer variable y.

Page 30: 3d7b7 session4 c++

• However, some type conversions are inherently unsafe, and if the compiler can detect that an unsafe conversion is being implicitly requested, it will issue a warning.

• For example if we write the code as belowint nValue = 3.14156; // implicit conversion to integer value

3

Here the fractional part of the double value 3.14156 is dropped because int type can not support fractional values.

Page 31: 3d7b7 session4 c++

• Because converting a double to an int usually causes data loss (making it unsafe), compilers such as Visual Studio Express 2005 will typically issue a warning.

• Few unsafe automatic conversions could be– assigning unsigned variables to signed

variables (and vice-versa),– assigning large integers (eg. a 4-byte long) to

integer variables of a smaller size (eg. a 2-byte short).

Page 32: 3d7b7 session4 c++

Explicit Conversion

• Explicit conversion can be done using type cast operator and the general syntax for doing this is

datatype (expression);

• Here in the above datatype is the type which the programmer wants the expression to gets changed

• This is called c++ style casting

Page 33: 3d7b7 session4 c++

#include <iostream.h>void main(){

int a;float b,c;cout<< “Enter the value of a:”;cin>>a;cout<< “n Enter the value of b:”;cin>>b;c = float(a)+b;cout<<”n The value of c is:”<<c;

}

Output isEnter the value of a: 10Enter the value of b: 12.5The value of c is: 22.5

Page 34: 3d7b7 session4 c++

• In the above program a is declared as integer and b and c are declared as float. In the type conversion statement namely

c = float (a) + b;

• The variable a of type integer is converted into float type and so the value 10 is converted as 10.0 and then is added with the float variable b with value 12.5 giving a resultant float variable c with value as 22.5

Page 35: 3d7b7 session4 c++

Inheritance

• Inheritance allows one data type to acquire properties of other data types.

• Inheritance allows to create classes which are derived from other classes, so that they automatically include some of its "parent's" members, plus its own.

• The original class is called the base class and the new class created using base class is called derived class.

Page 36: 3d7b7 session4 c++

• For example, we are going to suppose that we want to declare a series of classes that describe polygons like our CRectangle, or like CTriangle. They have certain common properties, such as both can be described by means of only two sides: height and base.

• This could be represented in the world of classes with a class CPolygon from which we would derive the two other ones: CRectangle and CTriangle.

• The class CPolygon would contain members that are common for both types of polygon. In our case: width and height. And CRectangle and CTriangle would be its derived classes, with specific features that are different from one type of polygon to the other.

Page 37: 3d7b7 session4 c++

NEED FOR INHERITANCENEED FOR INHERITANCE

• Capability to express the inheritance relationship-This ensures the closeness with the real world models.

• Reusability-The advantage of reusability are: faster development time and easier maintenance.

• Transitive nature of inheritance-If a class B inherits properties of another class A then all subclasses of B will automatically inherits the properties of A. This property is called transitive nature of inheritance.

Page 38: 3d7b7 session4 c++

Syntax

• In order to derive a class from another, we use a colon (:) in the declaration of the derived class using the following format:

class derived_class_name: public base_class_name{ /*...*/ };

Here derived_class_name is the name of the derived class and base_class_name is the name of the class on which it is based.

Page 39: 3d7b7 session4 c++

// Example derived classes #include <iostream> using namespace std; class CPolygon {

protected: int width, height;

public: void set_values (int a, int b) {

width=a; height=b;}

}; class CRectangle: public CPolygon {

public: int area () { return (width * height);

} };

class CTriangle: public CPolygon { public: int area () {

return (width * height / 2); }

};

Page 40: 3d7b7 session4 c++

• We can use the above created classes asint main () {

CRectangle rect; CTriangle trgl; rect.set_values (4,5); trgl.set_values (4,5); cout << rect.area() << “\n”; cout << trgl.area() << “\n”; return 0;

}

• The objects of the classes CRectangle and CTriangle each contain members inherited from CPolygon. These are: width, height and set_values().

• That’s is why we are using these members in main() method on the objects of classes CRectangle and CTriangle.

Page 41: 3d7b7 session4 c++

• In CPolygon Class we used protected access specifier• The protected access specifier is similar to private. Its

only difference occurs in fact with inheritance.• When a class inherits from another one, the members of

the derived class can access the protected members inherited from the base class, but not its private members.

• Since we wanted width and height to be accessible from members of the derived classes CRectangle and CTriangle and not only by members of CPolygon, we have used protected access instead of private.

Page 42: 3d7b7 session4 c++

• We can summarize the different access types according to who can access them in the following way:

Access public protected Private

members of the same class

yes yes yes

members of the derived class

yes yes no

not members yes no no

• Here "not members" represent any access from outside the class, such as from main(), from another class or from a function.

Page 43: 3d7b7 session4 c++

protected inheritance

• So far we have code written like

class B : public A {}

This means that the class B is publicily derived from B.

• We can specify protected derivation as well as

class B : protected A {}• If we specify a more restrictive access level like

protected, all public members of the base class are inherited as protected in the derived class.

Page 44: 3d7b7 session4 c++

• For example, if we write the code asclass CRectangle: protected CPolygon { ... }

• Then the function set_values() defined public in CPolygon will become protected in class CRectangle and we can not write code like

CRectangle rect; rect.set_values (4,5); // Error

Page 45: 3d7b7 session4 c++

private inheritance

• As we can have public and protected base class, we can also have private base class.

• We can specify private derivation as well as

class B : private A {}• If we specify a more restrictive access level like

private, all public and protected members of the base class are inherited as private in the derived class.

Page 46: 3d7b7 session4 c++

• For example, if we write the code asclass CRectangle: private CPolygon {

public: int area () { return (width * height);

}

}; The above code will not compile, because• We are inheriting CPolygon as private

base class, hence the protected members width & height become private

Page 47: 3d7b7 session4 c++

Types of Inheritance

• Single Inheritance - When a subclass inherits only from one base class,it is known as single inheritance.

class B: public A {}

Page 48: 3d7b7 session4 c++

• Multiple Inheritance - When a subclass inherits from multiple base classes, it is known as multiple inheritance.

class C: public A, public B {

}

Page 49: 3d7b7 session4 c++

• Hierarchical Inheritance - When many sub classes inherits from a single base class,it is known as hierarchical inheritance.

Page 50: 3d7b7 session4 c++

• Multilevel Inheritance - When a subclass inherits from a class that itself inherits from another class,it is known as multilevel inheritance.

class B: public A {

}

class C : public B {

}

Page 51: 3d7b7 session4 c++

• Hybrid Inheritance - When a subclass inherits from multiple base classes and all of its base classes inherits from a single base class,this form of inheritance is known as hybrid inheritance.

Page 52: 3d7b7 session4 c++

Constructors & inheritance

• Suppose I have a class B derived from A asclass B : public A {

public:B () {};B (int i) {};

}

• If I create an object asB b;

Then how the constructor of class A is called as we are creating the object of class B only?

Page 53: 3d7b7 session4 c++

The rule is :

• Whenever we create an object of derived class then constructor of base is called automatically even if we do not call them explicitly.

• If we are using multilevel inheritance then the call to constructor is starting from the first base class till the most derived class.

Page 54: 3d7b7 session4 c++

// Exampleclass A {public:

A () { cout << “In A’s Constructor \n”;

}}class B : public A {

public:B () {

cout << “In B’s Constructor \n”;}

}

class C : public B {public:C () {

cout << “In C’s Constructor \n”;}

}

Page 55: 3d7b7 session4 c++

main() {C c;

}

Output will beIn A’s ConstructorIn B’s ConstructorIn C’s Constructor

Here we are creating an object of class C, so the constructor of class A is called first, then B and then C.

Page 56: 3d7b7 session4 c++

Destructor

• Like constructor, destructor of base is called automatically when the object of derived class s destroyed or deleted or goes out of scope

• But the destructors are called in reverse order of the constructor call.

• The destructor of derived is called first, then of its base class and so on.

Page 57: 3d7b7 session4 c++

// Exampleclass A {public:

A () { cout << “In A’s Constructor \n”;

}

~A () { cout << “In A’s Destructor \n”;

}

}class B : public A {

public:B () {

cout << “In B’s Constructor \n”;}

~B () { cout << “In B’s Destructor \n”;

}

}

class C : public B {public:C () {

cout << “In C’s Constructor \n”;}~C () {

cout << “In C’s Destructor \n”;}

}

Page 58: 3d7b7 session4 c++

main() {C c;

}

Output will beIn A’s ConstructorIn B’s ConstructorIn C’s ConstructorIn C’s DestructorIn B’s DestructorIn A’s Destructor

Page 59: 3d7b7 session4 c++

Multiple inheritance and ambiguity

• We can inherit a class form more than one class and call id multiple inheritance.

• Consider a inheritance situation as below:A

member - i

B : public A

member – i of A

C : public A

member – i of A

D : public B,C

member – I of A via B

Member – I of A via C

Page 60: 3d7b7 session4 c++

• Here, the class D is derived form B and C. And both B and C are derived from A.

• That means we have two copy of class A in class D.

• When we create an object of class D, there are two i of A, one instance via class B and other instance of i via class C.

• If I write a code like:D d;d.i; // Error

Compiler is not able to resolve i in D as it has its two instances.

Page 61: 3d7b7 session4 c++

Virtual base class

• Duplication of inherited members due to these multiple paths can be avoided by making the common base class as virtual base class while declaring the direct or intermediate base clases.

• Like we can declare the A as virtual base class when we inherit the A in B and C

Page 62: 3d7b7 session4 c++

// Exampleclass A {public:

int i;

}class B : public virtual A {

………..}class C : public virtual A {

………..}class D : public C,D {

………..}

Page 63: 3d7b7 session4 c++

Virtual functions

• Before understanding the virtual fucntions, lets take a look at polymorphism.

• Pointers to base class– One of the key features of derived classes is that a

pointer to a derived class is type-compatible with a pointer to its base class. Polymorphism is the art of taking advantage of this simple but powerful and versatile feature, that brings Object Oriented Methodologies to its full potential.

Page 64: 3d7b7 session4 c++

// pointers to base class #include <iostream> using namespace std; class CPolygon {

protected: int width, height; public:

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

} };

class CRectangle: public CPolygon { public: int area () {

return (width * height); }

};

class CTriangle: public CPolygon { public: int area () {

return (width * height / 2); }

};

Page 65: 3d7b7 session4 c++

int main () { CRectangle rect; CTriangle trgl; CPolygon * ppoly1 = &rect; CPolygon * ppoly2 = &trgl; ppoly1->set_values (4,5); ppoly2->set_values (4,5); \cout << rect.area() << endl; cout << trgl.area() << endl; return 0;

}

• In function main, we create two pointers that point to objects of class CPolygon (ppoly1 and ppoly2). Then we assign references to rect and trgl to these pointers, and because both are objects of classes derived from CPolygon, both are valid assignment operations.

Page 66: 3d7b7 session4 c++

• The only limitation in using *ppoly1 and *ppoly2 instead of rect and trgl is that both *ppoly1 and *ppoly2 are of type CPolygon* and therefore we can only use these pointers to refer to the members that CRectangle and CTriangle inherit from CPolygon.

• For that reason when we call the area() members at the end of the program we have had to use directly the objects rect and trgl instead of the pointers *ppoly1 and *ppoly2.

• In order to use area() with the pointers to class CPolygon, this member should also have been declared in the class CPolygon, and not only in its derived classes, but the problem is that CRectangle and CTriangle implement different versions of area, therefore we cannot implement it in the base class. This is when virtual members become handy.

Page 67: 3d7b7 session4 c++

Members declared as virtual

• A member of a class that can be redefined in its derived classes is known as a virtual member.

• In order to declare a member of a class as virtual, we must precede its declaration with the keyword virtual.

virtual returntype function_name (parameters)

Page 68: 3d7b7 session4 c++

// pointers to base class #include <iostream> using namespace std; class CPolygon {

protected: int width, height; public:

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

} virtual int area () {

return (0); }

};

class CRectangle: public CPolygon { public: int area () {

return (width * height); }

};

class CTriangle: public CPolygon { public: int area () {

return (width * height / 2); }

};

Page 69: 3d7b7 session4 c++

• Now the three classes (CPolygon, CRectangle and CTriangle) have all the same members: width, height, set_values() and area().

int main () { CRectangle rect; CTriangle trgl; CPolygon poly; CPolygon * ppoly1 = &rect; CPolygon * ppoly2 = &trgl; CPolygon * ppoly3 = &poly; ppoly1->set_values (4,5); ppoly2->set_values (4,5); ppoly3->set_values (4,5); cout << ppoly1->area() << endl; cout << ppoly2->area() << endl; cout << ppoly3->area() << endl; return 0;

}

Page 70: 3d7b7 session4 c++

• The member function area() has been declared as virtual in the base class because it is later redefined in each derived class.

• Now when we do the following CRectangle rect;

CPolygon * ppoly1 = &rect; ppoly1->set_values (4,5); cout << ppoly1->area() << endl;

Here the arear() method of appropriate class i.e. CRectangle is called because area() is declared as virtual in base class.

• You can verify if you want that if you remove this virtual keyword from the declaration of area() within CPolygon, and then you run the program the result will be 0 for the three polygons instead of 20, 10 and 0.

Page 71: 3d7b7 session4 c++

• That is because instead of calling the corresponding area() function for each object (CRectangle::area(), CTriangle::area() and CPolygon::area(), respectively), CPolygon::area() will be called in all cases since the calls are via a pointer whose type is CPolygon*.

• Rule is:When a function is declared virtual in base class, then the function call via base class pointer is resolved at runtime and the function called is of the class whose object it is.

Page 72: 3d7b7 session4 c++

• Therefore, what the virtual keyword does is to allow a member of a derived class with the same name as one in the base class to be appropriately called from a pointer, and more precisely when the type of the pointer is a pointer to the base class but is pointing to an object of the derived class, as in the above example.

• A class that declares or inherits a virtual function is called a polymorphic class.

• The resolving of function at runtime depending upon the type of object is called dynamic polymorphism.

Page 73: 3d7b7 session4 c++

Abstract base class

• Abstract base classes are something very similar to our CPolygon class of our previous example.

• The only difference is that in our previous example we have defined a valid area() function with a minimal functionality for objects that were of class CPolygon (like the object poly),

• whereas in an abstract base classes we could leave that area() member function without implementation at all.

• This is done by appending =0 (equal to zero) to the function declaration.

• An abstract base CPolygon class could look like this:

Page 74: 3d7b7 session4 c++

// abstract class CPolygon class CPolygon {

protected: int width, height; public:

void set_values (int a, int b) {

width=a; height=b;

} virtual int area () =0;

};

• Notice how we appended =0 to virtual int area () instead of specifying an implementation for the function. This type of function is called a pure virtual function, and all classes that contain at least one pure virtual function are abstract base classes.

Page 75: 3d7b7 session4 c++

• Important : The main difference between an abstract base class and a regular polymorphic class is that because in abstract base classes at least one of its members lacks implementation we cannot create instances (objects) of it.

• But a class that cannot instantiate objects is not totally useless. We can create pointers to it and take advantage of all its polymorphic abilities. Therefore a declaration like:

 CPolygon poly;

would not be valid for the abstract base class we have just declared, because tries to instantiate an object. Nevertheless, the following pointers are valid:

CPolygon * ppoly1; CPolygon * ppoly2;

• This is so for as long as CPolygon includes a pure virtual function and therefore it's an abstract base class. However, pointers to this abstract base class can be used to point to objects of derived classes.

Page 76: 3d7b7 session4 c++

int main () { CRectangle rect; CTriangle trgl; CPolygon * ppoly1 = &rect; CPolygon * ppoly2 = &trgl; ppoly1->set_values (4,5); ppoly2->set_values (4,5); cout << ppoly1->area() << endl; cout << ppoly2->area() << endl; return 0;

} • If you review the program you will notice that we refer to

objects of different but related classes using a unique type of pointer (CPolygon*). This can be tremendously useful and called dynamic polymorphism.

Page 77: 3d7b7 session4 c++

Thank You

77