Go4Expert

Go4Expert (http://www.go4expert.com/)
-   C++ (http://www.go4expert.com/articles/cpp-tutorials/)
-   -   Virtual Functions in C++ Part I (http://www.go4expert.com/articles/virtual-functions-cpp-part-i-t29381/)

Trinity 29Dec2012 17:08

Virtual Functions in C++ Part I
 
Virtual functions in C++ play an important role. To understand virtual function, one should be clear about the polymorphism feature of C++ language as an object oriented language. In brevity, polymorphism is the weapon through which we can identify a function call through its parameters, or different types of parameters or maybe in base and derived class relationship. However, the behavior of function call decided at the compile time is called static polymorphism and the one decided at the runtime is called dynamic polymorphism. Virtual functions come into picture in case of dynamic polymorphism, which includes usage of pointers involving the derived and base class objects to decide which function behavior would be called.

Introduction



The virtual functions are defined in a base class, where same signature function is being defined in the derived class, making the base class function also getting publically inherited by the derived classes. So now, which function needs to be called i.e. one which is defined in the base class, or the one that is defined in the derived? This dynamic binding happens at runtime, and is leveraged using virtual functions.
A virtual function prototype looks as:
Code:


virtual int printData();

We shall be going in more details, when to use and how it works in further sections.

Using Virtual functions



Let us understand a scenario where we would need to use virtual functions. We would be designing and coding classes for a basic integer arithmetic calculations. As a simple design paradigm, we'll be having a base class with a bare minimum integer operand and an abstract calculate method. Each specific arithmetic operation can be handled as a separate class.
Code:


class baseArithmetic
{
public:
        int operand1;
        int compute()
        {
                return operand1;
        }
};

The baseArithmetic class has a bare minimum one operand, and a compute() method which returns the operand, as the base class does not implement any specific arithmetic operation. Moving on to the specific arithmetic operation classes, which gets inherited from the above base class. Following are the class definitions of Add, Subtract, Multiply and Divide.
Code:


class Add : public  baseArithmetic
{
public:
        int operand2;
        int compute()
        {
            int result = 0;
            result = operand1 + operand2;
            return result;
        }
};
class Subtract : public  baseArithmetic
{
public:
        int operand2;
        int compute()
        {
            int result = 0;
            result = operand1 - operand2;
            return result;
        }
};

class Multiply : public  baseArithmetic
{
public:
        int operand2;
        int compute()
        {
            int result = 0;
            result = operand1 * operand2;
            return result;
        }
};

class Divide : public  baseArithmetic
{
public:
        int operand2;
        int compute()
        {
            int result  = 0;
            if (operand2)
                result = operand1 /operand2;
            return result;
        }
};

Now we have the design ready, let us now try to use these classes to write our program.
Code:

int main()
{
        baseArithmetic *ba = NULL;
        int operation;
        int op1, op2;
        int result = -1;
        cout << "Enter number corresponding to what operation you want to do: - \n";
        cout << "1. Add\n2. Subtract\n3. Multiply\n4. Divide\n";
        cin >> operation;
        cout << "Enter the operators, first and second\n";
        cin >> op1 >> op2;
        switch (operation)
        {
            case 1:
        {
                Add da;
                    da.operand1 = op1;
            da.operand2 = op2;
                    ba = &da;
                        break;
        }
            case 2:
        {
                        Subtract ds;
            ds.operand1 = op1;
                    ds.operand2 = op2;
            ba = &ds;
                        break;
        }
            case 3:
        {
                        Multiply dm;
            dm.operand1 = op1;
                    dm.operand2 = op2;
            ba = &dm;
                        break;
        }
            case 4:
        {
                Divide dd;
                    dd.operand1 = op1;
            dd.operand2 = op2;
                    ba = &dd;
                break;
}
            default:
                cout<< "Invalid operator number\n";
                return 1;
        }
        result = ba->compute();
        cout << "The result is "<< result<< endl;
        return 0;
}

Now, we have the source ready to compile and run.
Code:


ubuntu@ubuntu-VirtualBox:~$ g++ main.cpp -o main
ubuntu@ubuntu-VirtualBox:~$ ./main
Enter number corresponding to what operation you want to do: -
1. Add
2. Subtract
3. Multiply
4. Divide
1
Enter the operators, first and second
3
6
The result is 3
$./main

Oh! It is incorrect. Addition of 3 and 6 cannot be 3. If we observe the result we obtained, it is actually the base class function which got called. The reason was, the pointer 'ba' is a pointer of type 'baseArithmetic'. Hence, when the 'compute()' method is called using this pointer, base method is called.

How to do make it work as we desire? It is using the virtual function. Here, we would have to declare 'compute()' function of the base class as virtual, so that if the derived class has same signature function, derived one will be called if the pointer contains object of the derived class.

This is how now our base class 'baseArithmetic' looks, including the virtual function.
Code:

class baseArithmetic
{
public:
        int operand1;
        virtual int compute()
        {
                return operand1;
        }
};

Making just this minor change to modify the base class function to a virtual function will rectify our program.

Compiling and running again,
Code:


ubuntu@ubuntu-VirtualBox:~$ g++ main.cpp -o main
ubuntu@ubuntu-VirtualBox:~$ ./main
Enter number corresponding to what operation you want to do: -
1. Add
2. Subtract
3. Multiply
4. Divide
1
Enter the operators, first and second
3
6
The result is 9

It runs as expected now.

The Function Signature



In the case of overriding or virtual functions, there is an implicit requirement of the function signature should be the same. The function signature includes the name of the function and the return type.
In the following prototype,
Code:


int function(int a, int b);

For the above function prototype, function signature is considered as
Code:


int func

Hence, a virtual function is a legitimate virtual function if the derived class holds a method with the same name and same return type i.e. the same function signature.
To look to an example,
Code:


class Base
{
public:
        virtual int func1();
        virtual int func2();
        virtual int func3();
};
class Derived : public Base
{
public:
        int func1();        //OK
        char func2();        //NOT OK
        int func3(int v);                //OK
};

Continue to Virtual Functions in C++ Part II


All times are GMT +5.5. The time now is 01:40.