Go4Expert

Go4Expert (http://www.go4expert.com/)
-   C++ (http://www.go4expert.com/articles/cpp-tutorials/)
-   -   Virtual, Static and Friend Functions in C++ (http://www.go4expert.com/articles/virtual-static-friend-functions-cpp-t29967/)

usmanmalik 12Jan2014 21:24

Virtual, Static and Friend Functions in C++
 
Whenever you hear the word virtual, the first thing which comes to your mind is something that only exists in appearance but in reality you cannot physically see or touch that thing. A virtual function in C++ is a similar concept. Virtual functions lays at the heart of object oriented programming and several advanced OOP features such as polymorphism extensively use polymorphism. We showed you a glimpse of how a virtual function is used in inheritance article. In this tutorial we are going to study virtual functions in detail along with their variations such as static, abstract and pure virtual functions etc.

Virtual Functions and Polymorphism



In the inheritance article, we explained how we can use virtual functions to implement inheritance. But virtual functions are not limited to inheritance; they have far larger impact on the Object Oriented Programming. Virtual functions also play an integral role in Polymorphism.

Polymorphism is an object oriented concept where two derived or child classes have a method with same name but different functionality. Suppose, we have three shapes: circle, square and rectangle. All of these shapes are different in appearance and drawn in different ways. Suppose we want to draw all of these shapes using their objects, we will do something like we did in example1.

Example1 (Calling drawshape() without polymorphism)
Code:

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

class Square
{

public:
        void drawshape()
        {
                cout<<"The Square has been drawn."<<endl;
        }
};

class Circle
{

public:
        void drawshape()
        {
                cout<<"The circle has been drawn."<<endl;
        }
};

class Triangle
{

public:
        void drawshape()
        {
                cout<<"The Triangle has been drawn."<<endl;
        }
};
int main()
{

        Circle c;
        Square s;
        Triangle t;

        s.drawshape();
        c.drawshape();
        t.drawshape();
}

Output1

http://imgs.g4estatic.com/articles/v...on/output1.png

In Example1, we have created three classes named Square, Circle and Triangle. All of these three classes have a function named drawshape(). In order to call this function we had to create object of each of these three classes and called their drawshape() function. This technique is verbose, unstructured and unorganized. We want that, we create a single object variable that can store all of these three shapes and when we call drawshape(), the function calls that class’s function whose instance has been stored in the object variable. This is what we call polymorphism. We will have single variable of class shape that will be able to store all three shapes object and when we call drawfunction(), the draw function intrinsic to the object being stored will be called. This functionality has been achieved in Example2 where we have implemented polymorphism.

Example2 (Calling drawshape() using polymorphism)
Code:

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

class Shape
{

public:
        virtual void drawshape()
        {
                cout<<"Drawshape base class";
        }
};

class Square: public Shape
{

public:
        void drawshape()
        {
                cout<<"The Square has been drawn."<<endl;
        }
};

class Circle: public Shape
{

public:
        void drawshape()
        {
                cout<<"The circle has been drawn."<<endl;
        }
};

class Triangle: public Shape
{

public:
        void drawshape()
        {
                cout<<"The Triangle has been drawn."<<endl;
        }
};
int main()
{
        Shape * shape[3];
        Circle c;
        Square s;
        Triangle t;

        shape[0]= &c;
        shape[1]= &s;
        shape[2]= &t;

        for(int i =0; i<3; i++)
        {
                shape[i]->drawshape();
        }
       
}

Pay particular attention to the Example2. We have covered many important concepts in this Example that I am going to explain one by one.

First of all, you can see that we have created another class named Shape. We have then, derived our three shape classes: Square, Circle and Triangle from this Shape class. Note, in shape class we have defined a virtual function named drawshape(). In order to declare a function virtual, you just have to append virtual keyword before the function definition.

Now, We can see that all the child classes have their own drawshape() function. It means that the virtual function drawshape() in the base class has been overridden by the child classes.

Next, we have defined three variables s, c and t respectively for Square, Circle and Triangle class.

The fun begins after that. We have declared a pointer array of type shape. Each index of this array is capable of pointing towards the memory address of the variable of type shape. We know that up-casting is implicit in C++. This means that we can store the derived class variables in base class. Therefore, we store the address of all the derived class variables s, c and t in the pointer array index.

An important thing to note here is that in order to access the function of a object from the pointer variable we use ‘->’ arrow.

Therefore, in our code inside the loop we called the drawshape() function from each array index using ->. The most amazing thing here is that although we are calling the same drawshape() function from the pointer array, internally the drawshape() function of the individual objects s, c and t are called. Index 0, 1 and 2 holds variables c, s and t as we defined in the code but externally we are calling a single drawshape() function which is behaving in multiple ways. This is what polymorphism is all about; a single interface but multiple functionalities. The output of this code will be similar to Example1’s code but here the code is more organized and structured by implementing polymorphism. The output of Example2 is as under:

Output2

http://imgs.g4estatic.com/articles/v...on/output2.png

Static Functions and Member Functions



Static functions and members can be simply defined as the functions and members which can be accessed through the class name. We do not need to create the instance/object of the class in order to access the static members of the class. Static members are per class where as non-static members are per instance. An interesting thing is that value of the static members of the class is same for all objects and if static member is publicly defined, any object of the class can modify the value of static members and this value will be updated for all the instances.

You would have seen the main function. Although, this is not specified static but internally this function is also static. It is due to this reason we do not have to create the object of the class in the start because we have to enter into the program from somewhere and main function allows us to enter the code without specifying any object of the class in the beginning. In our next Example we are going to explain the concept of static function and members in detail. Have a look at Example3.

Example3
Code:

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

class ObjectCounter
{

public:
        static int numofobjects;
public:
        ObjectCounter()
        {
                numofobjects ++;
        }
        static void showcount()
        {
                cout<<"Total number of Objects is: "<<numofobjects<<endl;
        }
};

int ObjectCounter ::numofobjects = 0;

int main()
{
        ObjectCounter::showcount();
        ObjectCounter a, b, c;
        cout<<"After instantiating ObjectCounter Class thrice."<<endl;
        ObjectCounter::showcount();
}

Carefully examine the code in Example3. We have created a class named ObjectCounter. This class has one static member numofobjects and a static function called showcount(). Inside the counter of the class we are incrementing static member numofobjects. The function showcount() is a static function which displays the number of objects of the class. Remember, whenever the object of this class will be created, the constructor will be called and static member numofobjects will be incremented. This way we can keep track of the number of objects of the particular class.

Here an interesting thing note is that we have to initialize the static member with some value and this initialization cannot be done inside the class body. Therefore we declare the variable static inside the class and define it outside the class using the scope resolution operator. Look at the following line of code

int ObjectCounter ::numofobjects = 0;

This line of code specifies that a static member of type integer is present in class ObjectCounter and we want to initialize it with value 0. The scope resolution ‘::’ operator is used if we want to assign some value to a class member outside the class.

Now come towards the main function. Inside the main function, in the very first line we have called the static function showcount(). Note the syntax of calling the static function. We did not create any object, rather in order to call the static function we simply wrote the class name, followed by the scope resolution operator and finally the function we want to call.

Since, we have not created any object of the class ObjectCounter until yet, the static member numofobjects will have value zero at the moment.

In the next line we have created three objects of class ObjectCounter. Every time an object is created the constructor will be called and numofobjects static member will be incremented. We created three objects; therefore the numofobjects will be three. We again called the showcount() static function of the ObjectCounter class using scope resolution and it will display the value of the numofobjects variable on screen. The output of Example3 is as follows.

Output3

http://imgs.g4estatic.com/articles/v...on/output3.png

Friend Functions



We showed you a glimpse of friend functions in the Operator Overloading article, here in this article; we are going in further detail of friend functions. Object Oriented Programming is based on three pillars: Polymorphism, Inheritance and Encapsulation. They are also sometimes referred as PIE. We already know what polymorphism and inheritance is. Coming towards the encapsulation; Encapsulation stresses that the member variables of the class should not be accessed by any function other than the member function. This means that data of the class should be hidden and other classes interact with this data through the member function. They cannot directly access the data of the class. We do this by making member variables private.

However, often times we need a function which is not the part of the class but can access the private member. For Example, what if you want a function that can access the members of multiple classes? Suppose you want a method which can take objects of two different classes and want to add members of the two objects. In such cases C++ provides us a mechanism. This is done via friend function. Friend function is basically a function which is declared inside the body of all such classes where we want to access the private members. Friend functions are declared using the keyword friend. In the following example we are going to use friend function which act as a bridge between two classes and adds their member variable.

Example4
Code:

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

class B;

class A
{

private:
        int number1;
        public:
        A(int num1)
        {
                number1 = num1;
        }
        friend int friendbridge(A, B);
};


class B
{

private:
        int number2;
public:
        B(int num2)
        {
                number2 = num2;
        }
        friend int friendbridge(A, B);
};

int friendbridge(A a, B b)
{
        return a.number1+b.number2;
}
int main()
{
        A a(10);
        B b(20);

        cout<<"The sum of numbers of object A and B is: "<<friendbridge(a,b);
       
        getchar(); // Just To Prevent Screen from Disappearing
        cin.get(); // Just To Prevent Screen from Disappearing
}

Have a look at the Example4, In this example we have declared class B before class A’s definition but we haven’t defined class B. This is due to the reason that we have a friend function named friendbridge inside class A and it takes two parameters, one object of class A and the other object of class B therefore we had to declare class B before A. After the definition of class A, we have defined class B and again added friend function friendbridge in this class B. Now we have a function that is in both the classes and can access the private members of both Class A and Class B. There is a variable number1 in class A and number2 in class B. Both of these variables are private.

Now come towards the definition of the friend function named friendbridge. This function takes two objects of class A and B respectively as parameter and then adds number1 from Class A’s object to number2 member of class B. Both number1 and number2 are private in their respective classes but they can be accessed via friend function. In main function we have created two objects ‘a’ and ‘b’ and have passed values 10 and 20 in the constructor which will be stored in number1 and number2 respectively. We have then displayed the result of the friend function on the screen which will be the sum of two variables, number1 from object a and number2 from object b. The output of Example4 will be as follows:

Output4

http://imgs.g4estatic.com/articles/v...on/output4.png

In this article, we have explained three concepts, virtual functions, static functions and friend functions. We have also explained polymorphism using virtual function. You should further explore these concepts yourself and in case if you need any help, comment below and I will be back to you. Also, keep visiting this site for more interesting and handy tutorials on C++.


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