Headlines News :
Home » , , » Learn C++ in 12 Days - Day 8

Learn C++ in 12 Days - Day 8

Written By Ente Malayalam on Friday, May 24, 2013 | 5/24/2013

DAY – 8

Till yesterday’s class we have seen features added along with member functions of the class to make the encapsulation more efficient. In today’s class we will c few features added along with data members of the class which in turn increases the efficiency of encapsulation. 
            The two features we are going to c in today’s class is static and constant.

Static members:
            You might have learnt about static data members in your C language right. The same old theory is applicable in C++ also. Lets take an eg:

int add();
main()
{
            int c = add();
            cout << c << endl;
c = add();
            cout << c << endl;
c = add();
            cout << c << endl;
}

int add()
            int i = 0;
            i++;
            return I;
}

{
If you see the output here , you can see that all the three cout statements prints 1 only. This is because, in the function add, i is declared as a local variable which gets constructed when the function is invoked and which gets destroyed when the function ends. A slight modification in the above program changes the entire output. For eg:

int add();
main()
{
            int c = add();
            cout << c << endl;
c = add();
            cout << c << endl;
c = add();
            cout << c << endl;
}

int add()
{
            static int i = 0;
            i++;
            return i;
}

If you notice the output here, you can c that it will print you 1, 2 and 3. So what s happening here.
At this point, you should remember the basic rules of static variables. Static members gets memory only once in your program. The memory for static variables will be allocated in the data segment and the allocation will be taken care of by the compiler. Now correlating these rules to the above program : here the variable i gets memory only once. That means, it wont be destroyed when the add function ends. Its scope is till the program / main ends. So each and every time the function is called, the same memory location allocated first time will be getting manipulated giving us the appearance that the variable i retains its value after each and every function call.
We are going to apply the same rules to our class data members and function members. Lets deal with the data members and function members separately.

Static data members:
            Usually members of a class will be getting memory at the time of creation of objects. Ie) each and every object will be having its own copies of data members. When the data member of a class is made as static, since memory can be allocated only once, each and every object will be forced to share this single memory location. Since it is a shared property, none of the objects will consider this static variable at the time of allocation of memory. That means static variables wont be getting memory at the time of creation of objects. So it is our responsibility to explicitly instruct our compiler to take care of the memory allocation. To do this, we have to re-declare the static variable outside the class. First lets c a sample program to c how we have to re-declare it. Then we will move on to an application program.

class myclass   {
            private:
                        Static int a;
                        Int b;
            public:
                        myclass(int p, int q)     {
                                    a = p;  
                                    b = q;
                        }
                        void display()  {
                                    cout << a << endl;
                                    cout << b << endl;
                        }
};

int myclass :: a;

So here we are telling our compiler that the variable a  belonging to the scope of myclass is a static variable. So please take care of its memory allocation. Lets try to write the main of this program.

main()
{
            myclass obj1(10, 20);
            obj1.display();
            myclass obj2(100, 200);
            obj2.display();
            obj1.display();
}

If you notice the output here :
 10
20
100
200
100
20
You can see that the changes made by one object on the static variable is directly getting reflected on the other. As you can guess, it is because the memory allocated for static variable is shared between obj1 and obj2.
            We can apply the concept of static to our function members also.

Static member functions.
            Just like static data members, static member functions are also independent of the objects. And the most interesting thing about static function members is it can access only static data members. This is because, since the static member functions are independent of the objects, it is perfectly legal to access them even before the creation of objects. The normal data member of the class gets memory only at the time of creation of objects. So naturally static member functions cannot access them before creating objects. The only data member who gets memory even before the creation of objects is static data members. So the static member functions can access only static data members.
Or simply stating, since static member functions are independent of the object, there wont be any this pointer associated with it. So it cannot access any data member which has a this pointer. The syntax for static member function defined inside the class is

class class_name          {
            public:
                        Static return type function name(function arg)          {}
};
When declared inside and defined outside, the syntax of static member function changes a little.

            class class_name          {
                        public:
                                    static ret-type fun-name(fun-arg);
            };
            Ret_type class name :: fn-name(fun arg)        {}

If you notice you can see that static keyword have to be supplied only in the declaration and not in the definition.
Let’s learn about constant data members and function members also. Then we will come to an application program.

Constant data members:
            As you know, the members defined as constant cannot be modified in the program. The same rule is applicable to data members made as constant in the class. But while declaring a variable as constant there are few things which you have to worry about. When you declare a variable as constant, you need to initialize it at the time of declaration itself. Else it will throw you an error. But when you declare a variable inside the class, it is not legal to initialize it there since there wont be any memory allocated till we create an object. Or simply saying, class is just a plan / template. So initializing at the time of declaration inside the class will be like putting mud on the paper where you have drawn the house plan. So what to do? In this type of situations we have to seek the help of a new technique termed as initialization through member initializer list. The syntax is
                        Constructor() : var(), var()       {}

Lets take an eg:

class myclass   {
            private:
                        Const int x;
                        Const int y;
            public:
                        Myclass() : x(10), y(20)           {}
                       
};

main()
{
            myclass obj;
}

Here x and y are constant variables initialized through member initializer list. This is the only way you can initialize a constant variable.
            There is one more application for this member initializer list. It is regarding reference variable. We have already learnt that a reference variable declared needs to get initialized at the time of declaration itself. So a variable declared as reference to another variable in the class needs to get initialized at the time of declaration. Since it is not practically possible we have to seek the help of member initializer list. Consider the following eg:

class myclass   {
            private:
                        int x;
                        int &y;
            public:
                        myclass() : y(x)            {
                                    X = 10;
                        }
                       
};
main()
{
            myclass obj;
}
Again this is the only way we can initialize a reference variable inside the class.

Lets go back to our discussion regarding constants. The keyword const can be applied along with member function also and we call them as constant member functions.

Constant member functions:
            The syntax of constant member functions when defined inside the class is

class class-name          {
            public:
                        Ret-type fun-name(fun-arg) const      {}
};

Again the syntax changes slightly when declared and defined outside.

class class-name          {
            public:
                        Ret-type fun-name(fun-arg) const;
};

Ret-type class-name :: fn-name(fn-arg) const {}

If you notice you can see that unlike static functions, const keyword needs to be present in the declaration as well as definition.
            The specialty of constant member functions is that it can access any variables but it cannot modify any variables. So in constant member functions, the this pointer will be acting as a constant pointer to constant object. Because of this reason, constant member functions are termed as accessors.
Now lets combine static’s and constants and lets try to do the abstraction and encapsulation of an entity known as Car. Lets keep the class diagram as below.

 








            In the above abstraction we can make seating capacity and fuel capacity as constants. Since discount is something which is going to be common for all the cars, we can make discount as static.
            Among the behaviours, since discount should be fixed or viewed irrespective of a particular car, both the functions can be made as static where as since all other functions are simply acting as display functions or accessors we can make it as constants.
            The encapsulation of the above entity can be done as follows.











//car.h

#include <iostream>
using namespace std;

class Car       {
        private:
                char Make[20];
                char Model_Name[20];
                const int Seating_Capacity;
                const int Fuel_Capacity;
                float Price;
                static float Discount;
        public:
                Car() : Seating_Capacity(4), Fuel_Capacity(35)  {
                        strcpy(Make, "Hyundai");
                        strcpy(Model_Name, "Santro");
                        Price = 400000.00;
                }
                Car(char *m, char *n, int s, int f, float p) : Seating_Capacity(s), Fuel_Capacity(f)    {
                        strcpy(Make, m);
                        strcpy(Model_Name, n);
                        Price = p;
                }
                static void Set_Discount(float);
                static float Return_Discount();
                const char* Return_Model_Name() const;
                const char* Return_Make() const;
                float  Return_Price() const;
};

//car_library.cpp
#include "car.h"

float Car :: Discount = 0.05;

void Car :: Set_Discount(float D)       {
        Discount = D;
}

float Car :: Return_Discount()  {
        return Discount;
}


const char* Car :: Return_Make() const  {
        return Make;
}

const char* Car :: Return_Model_Name() const    {
        return Model_Name;
}

float Car :: Return_Price() const       {
        return Price;
}


//car_application.cpp
#include "car.h"

int main()      {
        Car Santro("Hyundai", "Santro", 4, 35, 400000.00);
        Car :: Set_Discount(0.10);
        cout << "Displaying Discount" << Car :: Return_Discount() << endl;
        cout << "Car Details" << endl;
        cout << Santro.Return_Make() << endl;
        cout << Santro.Return_Model_Name() << endl;
        cout << Santro.Return_Price() << endl;

        return 0;
}

            Now lets assume that while displaying price, I have to change it according to the discount and then return it. Is it possible ? no right: it is because return price() is a constant function which is not able to modify any value. But even this can be made possible in C++. Ie) I can make a constant function to modify a non constant value and it is achieved using something known as mutable.

Mutable:
            A variable declared as mutable is modifiable by a constant member function and it acts as a normal data member for other functions. So applying this concept and modifying the above class.
            Lets modify it and lets see the encapsulation of it







//car.h
#include <iostream>
using namespace std;

class Car       {
        private:
                char Make[20];
                char Model_Name[20];
                const int Seating_Capacity;
                const int Fuel_Capacity;
                mutable float Price;
                static float Discount;
        public:
                Car() : Seating_Capacity(4), Fuel_Capacity(35)  {
                        strcpy(Make, "Hyundai");
                        strcpy(Model_Name, "Santro");
                        Price = 400000.00;
                }
                Car(char *m, char *n, int s, int f, float p) : Seating_Capacity(s), Fuel_Capacity(f)    {
                        strcpy(Make, m);
                        strcpy(Model_Name, n);
                        Price = p;
                }
                static void Set_Discount(float);
                static float Return_Discount();
                const char* Return_Model_Name() const;
                const char* Return_Make() const;
                float  Return_Price() const;
};

//car_library.cpp
#include "car.h"

float Car :: Discount = 0.05;

void Car :: Set_Discount(float D)       {
        Discount = D;
}

float Car :: Return_Discount()  {
        return Discount;
}
const char* Car :: Return_Make() const  {
        return Make;
}

const char* Car :: Return_Model_Name() const    {
        return Model_Name;
}

float Car :: Return_Price() const       {
        if(Discount > 0.0)      {
                Price = Price - (Price * Discount);
                return Price;
        }
        else
                return Price;
}


//car_application.cpp
#include "car.h"

int main()      {
        Car Santro("Hyundai", "Santro", 4, 35, 400000.00);
        Car :: Set_Discount(0.10);
        cout << "Displaying Discount" << Car :: Return_Discount() << endl;
        cout << "Car Details" << endl;
        cout << Santro.Return_Make() << endl;
        cout << Santro.Return_Model_Name() << endl;
        cout << Santro.Return_Price() << endl;
        Car :: Set_Discount(0.0);
        cout << "Without discount" << Santro.Return_Price() << endl;

        return 0;
}




Share this article :

0 comments:

Post a Comment

 
Support : Creating Website | Johny Template | Maskolis | Johny Portal | Johny Magazine | Johny News | Johny Demosite
Copyright © 2011. Education World - All Rights Reserved
Template Modify by Creating Website Inspired Wordpress Hack
Proudly powered by Blogger