Virtual Functions in C++ Part I

Discussion in 'C++' started by Trinity, Dec 29, 2012.

  1. Trinity

    Trinity New Member

    Joined:
    Nov 23, 2011
    Messages:
    28
    Likes Received:
    11
    Trophy Points:
    3
    Occupation:
    Software Engineer
    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
     

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice