Instance Members and Static Members

In this tutorial of our C ++ course, we will clarify a little more about the variables of the objects as well as learn what static members are and how to use them in practice.


Instance members (of objects)

Static members in C++
Recalling our study of functions a little, we saw there that, commonly, the variables declared within a function are said to be local and temporary. Because they only exist within the function and are deleted from memory when the function ends. In classes, something similar occurs.
When we have a 'Car' class and the 'engine' attribute, we do:

  • BMW.engine = 4;
  • corolla.engine = 2;

Although the name of the variable is the same, each object has its own variable, where one does not change the other. That is, 'copies' of these variables are created.

Thus, the variables are specific to each instance, even though they have the same name and the objects originate from the same Class.


Static members of a Class

However, sometimes we do not want each instance to have its own attribute, it may be necessary to have an attribute that is exactly the same (same memory location), for all objects.

And it is possible to do this, for both variables and functions.

For example, suppose you are the programmer who will take care of a large company's system, and each time a person is hired, an Employee type object must be created. And each time an employee is fired, an object is deleted. How do you keep track of how many employees there are?

Simple, just create a static variable, which is incremented every time an object is instantiated and is decremented every time an object is deleted.


Static variable

To create a static variable, just use the static keyword before declaring the variable.

Let's create the class "Car.h":

#ifndef CAR_H
#define CAR_H


class Car
{
    public:
        Car();
        ~Car();
        int getTotal();

    private:
        static int total;
};

#endif // CAR_H

See that we declare the entire variable 'total' as static. Let's see the implementation, 'Car.cpp':

#include "Car.h"

int Car::total = 0;

Car::Car()
{
    total++;
}

Car::~Car()
{
    total--;
}

int Car::getTotal()
{
    return total;
}

The first thing we did was to initialize the total variable with 0, after all, initially, no object was instantiated. The constructor function simply increases the total value, that is, each time we instantiate an object, this variable will be increased.

And in the destructor function, we decrease this variable.

And since it is static, this value will represent the number of objects created from the Car class. See how our main.cpp looks like:

#include <iostream>
#include "Car.h"
using namespace std;

int main()
{
    Car *ptr1, *ptr2, *ptr3;
    ptr1 = new Car();
    ptr2 = new Car();
    ptr3 = new Car();

    cout<<"Number of instantiated objects: "<< (*ptr1).getTotal() <<endl;

    delete ptr3;
    cout<<"Number of instantiated objects: "<< (*ptr1).getTotal() <<endl;
return 0; }

First, we created three Car-type objects. Next, we do the dynamic memory allocation.

We print the result after these 3 allocations. We delete the third pointer (this causes the destructor ~ Car() function to be triggered), then print the number of instances again.

And the result is:

"Number of instantiated objects: 3"
"Number of instantiated objects: 2"

Note that we use the function of the first object, '*ptr1', which we created, this proves that the variable 'total' is the same, for all objects.


Static function

Just as static variables exist, we can also create static functions, for a class. However, they have a very specific characteristic: they can only act on static variables.

We will create the zero() function, which will reset the 'total' variable. Our "Car.h" class:

#ifndef CAR_H
#define CAR_H

class Car
{
    public:
        Car();
        ~Car();
        int getTotal();
        static void zero();

    private:
        static int total;
};

#endif // CAR_H

Our implementation "Car.cpp"

#include "Car.h"
int Car::total=0;

Car::Car()
{
    total++;
}

Car::~Car()
{
    total--;
}

int Car::getTotal()
{
    return total;
}

void Car::zero()
{
    total=0;
}

Finally, our main:

#include <iostream>
#include "Car.h"
using namespace std;

int main()
{

    Car *ptr1, *ptr2, *ptr3;
    ptr1 = new Car();
    ptr2 = new Car();
    ptr3 = new Car();

    cout<<"Number of instantiated objects: "<< (*ptr1).getTotal() <<endl;
delete ptr3;
    cout<<"Number of instantiated objects: "<< (*ptr1).getTotal() <<endl;
Car::zero();
    cout<<"Number of instantiated objects: "<< (*ptr1).getTotal() <<endl;
return 0; }

And the result is:

"Number of instantiated objects: 3"
"Number of instantiated objects: 2"
"Number of instantiated objects: 0"

An interesting thing about static members is that they exist even before any instance of the class is created. So, without creating any objects, you can already access 'total' and 'zero()'.

For example, you can ask the user for a value and use that value to change a static variable of a class, before even starting to instantiate objects from it, and start working with objects from a value previously determined by the user.

No comments:

Post a Comment