***Welcome to ashrafedu.blogspot.com * * * This website is maintained by ASHRAF***

Monday, June 14, 2021

Abstract classes

An abstract class is a class that is designed to be specifically used as a base class. An abstract class contains at least one pure virtual function.

The purpose of an abstract class is to provide an appropriate base class from which other classes can inherit. Abstract classes cannot be used to instantiate objects and serves only as an interface. Attempting to instantiate an object of an abstract class causes a compilation error.

Virtual member functions are inherited. A class derived from an abstract base class will also be abstract unless you override each pure virtual function in the derived class.

 

#include <iostream.h>

// Base class

class Shape {

   public:

      // pure virtual function providing interface framework.

      virtual int getArea() = 0;

      void setWidth(int w) {

         width = w;

      }

        void setHeight(int h) {

         height = h;

      }

  

   protected:

      int width;

      int height;

};

 // Derived classes

class Rectangle: public Shape {

   public:

      int getArea() {

         return (width * height);

      }

};

 class Triangle: public Shape {

   public:

      int getArea() {

         return (width * height)/2;

      }

};

 

void main(void) {

   Rectangle Rect;

   Triangle  Tri;

   Rect.setWidth(5);

   Rect.setHeight(7);

     // Print the area of the object.

   cout << "Total Rectangle area: " << Rect.getArea() << endl;

    Tri.setWidth(5);

   Tri.setHeight(7);

     // Print the area of the object.

   cout << "Total Triangle area: " << Tri.getArea() << endl;

}

output:

Total Rectangle area: 35

Total Triangle area: 17

PURE VIRTUAL FUNCTIONS

In practical applications the member functions of base classes are rarely used for doing any operation such functions are called as do-nothing functions or dummy functions or pure virtual functions.

Pure virtual functions are defined with null body, so that the derived classes can implement them.

syntax:

virtual void functionname( ) =0;

Ex:

virtual void display( ) =0;

Here the assignment operator is used just to instruct the compiler that the function is a pure virtual function and it will not have a definition.

The classes derived from pure abstract classes are required to redeclare the pure virtual function.

All these derived classes which redefine the pure virtual function are called as concrete classes.

These classes can be used to declare objects.

Ex:

#include<iostream.h>

#include<conio.h>

class first

{

protected:

int b;

public:

first()

{

b=10;

}

virtual void display() = 0;

};

class second : public first

{

int d;

public:

second()

{

d=20;

}

void display()

{

cout<<b<<d;

}

};

void main()

{

clrscr();

first *p;

second s;

p=&s;

p->display();

}

Polymorphism and virtual functions

Polymorphism is one of the important features in object-oriented programming language. Polymorphism is the ability to take more than form.

In Greek, “poly” means many “morphism” means forms. It means one function or operator contains more than one forms.

Polymorphism is of two types:

1. Compile-time polymorphism (Function Overloading & Operator Overloading)

2. Run-time polymorphism (Virtual Function)

Polymorphism supports two types of concepts – overloading and overriding. Overloading is possible through compile-time polymorphism. Overriding is possible through compile-time polymorphism.

When working with inheritance, if both base and derived classes are defined with the same member function with the same signature, then member function overriding may occur. To overcome this, dynamic polymorphism is used. The dynamic polymorphism requires virtual functions.

Virtual function:

A virtual function is a member function that is dynamically bound to function calls. In dynamic binding , C++ determines which function to call at runtime, depending on the type of the object responsible for the call.

Virtual functions are declared by placing the key word virtual before the return type in the base class’s function declaration, such as

public:

virtual returntype fun_name(arguments)

{

----------

statements;

}

This declaration tells the compiler to expect fun_name to be redefined in a derived class. The compiler does not bind calls to the function with the actual function. Instead, it allows the program to bind calls, at runtime, to the version of the function that belongs to the same class as the object responsible for the call.

Demonstrating Virtual Functions

#include<iostream.h>

#include<conio.h>

class Base

{

public:

void print()

{

cout<<"\nprint() in Base class";

}

virtual void show()

{

cout<<"\nshow() in Base class";

}

};

class Derived : public Base

{

public:

void print()

{

cout<<"\nprint() in Derived class";

}

void show()

{

cout<<"\nshow() in Derived class";

}

};

void main()

{

clrscr();

Base *ptr;                                                                                                                            

Base b;                                                                                                                                

ptr=&b;            

ptr->print();                                                            

Derived d;                                                                                                                           

ptr=&d;            

ptr->show();                                                                       

getch();                                                                                                                                

}

Output:

print() in Base class

show() in Derived class

Rules For Virtual Functions:

  • The virtual functions should not be static and must be member of a class.
  • A virtual function may be declared as friend of another class.
  • Constructors can’t be declared as virtual but destructors can be virtual.
  • The virtual function must be defined in the public section of the class.
  • The prototype of virtual functions in base and derived classes should be exactly the same.
  • In case of mismatch the compiler neglects the virtual function mechanism and treats them as overloaded function.
  • If a base class contain virtual function and if the same function is not redefined in the derived classes in that case the base class function is invoked.
  • The keyword virtual prevents the compiler to perform early binding. Binding is postponed until run time.
  • The operator keyword used for operator overloading also supports virtual mechanism.


Constructors and Destructors in Base and Derived Classes

When the constructors and destructors defined in both base and derived classes, consider the following:

1) If both base and derived class has constructors, the base class constructor is executed first and then the derived class constructor is executed.

2) If the base class constructor does not take any argument, the derived class may not have a constructor.

3) If the base class constructor with one or more arguments, then the derived class must have a constructor function to pass arguments to the base class constructor. It is defined as follows:

public:

Derived_classname(datatype arg1,datatype arg2) : base_classname(arg1)

{

Derived_class_variable = arg2;

}

For a base class constructor, the arguments must be passed by the derived class constructor.

4) The order of execution of destructors is just reverse of constructors, that is, first the destructor of derived class is called then the base class destructor is called.

Example:

#include <iostream.h>

class BaseClass

{

 public:

 BaseClass() // Constructor

 {

cout << "This is the BaseClass constructor.\n";

 }

 ~BaseClass() // Destructor

 {

cout << "This is the BaseClass destructor.\n";

 }

 };

class DerivedClass : public BaseClass

{

 public:

 DerivedClass() // Constructor

 {

cout << "This is the DerivedClass constructor.\n";

}

 ~DerivedClass() // Destructor

 {

 cout << "This is the DerivedClass destructor.\n";

 }

 };

void main()

{

 cout << "We will now define a DerivedClass object.\n";

 DerivedClass object;

 cout << "The program is now going to end.\n";

}

Output:

We will now define a DerivedClass object.

This is the BaseClass constructor.

This is the DerivedClass constructor.

The program is now going to end.

This is the DerivedClass destructor.

This is the BaseClass destructor.

 

//Demonstration on base constructor with argument

#include<iostream.h>

#include<conio.h>

class Base

{

protected:

int a;

public:

Base(int k)

{ a=k; }

};

class Derived : public Base

{

private:

int b;

public:

Derived(int p, int q) : Base(p)

{ b=q; }

void show()

{

cout<<"\nBase class a= "<<a;

cout<<"\nDerived class b= "<<b;

}

};

void main()

{

clrscr();

Derived d(10,5);

d.show();

getch();

}

Demonstration of multilevel inheritance

 

#include<iostream.h>

#include<conio.h>

class A

{

private:

int x;

public:

void getA()

{

cout<<"Enter x: ";

cin>>x;

}

void showA()

{

cout<<"X = "<<x<<endl;

}

};

class B : public A

{

private:

int y;

public:

void getB()

{

getA();

cout<<"Enter y: ";

cin>>y;

}

void showB()

{

showA();

cout<<"Y = "<<y<<endl;

}

};

class C : public B

{

public:

void getC()

{

getB();

}

void showC()

{

showB();

}

};

void main()

{

clrscr();

C obj;

obj.getC();

obj.showC();

getch();

}