Ajude nosso projeto a se manter online.

Membros de Instância e Membros Estáticos

 Neste tutorial de nosso curso de C++, vamos esclarecer um pouco mais sobre as variáveis dos objetos bem como aprender o que são membros estáticos e como usá-los na prática.


Membros de instâncias (objetos)

Membros estáticos de instância em C++
Recordando um pouco nosso estudo das funções, vimos lá que, comumente, as variáveis declaradas dentro de uma função, são ditas locais e temporárias. Pois só existem dentro da função e são deletadas da memória quando a função termina. Nas classes, ocorre algo parecido.

Quando temos uma classe 'Car' e o atributo 'engine', e fazemos:

BMW.engine = 4;
fusca.engine = 1;

Embora o nome da variável seja a mesma, cada objeto tem sua própria variável, onde uma não altera a outra. Ou seja, são criadas 'cópias' dessas variáveis.

Assim, as variáveis são próprias de cada instância, mesmo tendo o mesmo nome e os objetos se originando da mesma Classe.


Membros estáticos de uma Classe

Porém, as vezes não queremos que cada instância tenho seu próprio atributo, pode ser necessário ter um atributo que é exatamente o mesmo (mesmo local de memória), para todos os objetos.

E é possível fazer isso, tanto para variáveis como para funções.

Por exemplo, vamos supor que você é o programador que vai cuidar do sistema de uma grande empresa, e cada vez que uma pessoa é contratada, um objeto do tipo Funcionario deve ser criado. E cada vez que um funcionário é demitido, um objeto é excluído. Como manter o controle de quantos funcionários existem?

Simples, só criar uma variável estática, que é incrementada toda vez que um objeto for instanciado e é decrementada toda vez que um objeto for excluído.


Variável estática

Para criar uma variável estática, basta usar a palavra-chave static antes de declarar a variável.
Vamos criar a classe "Car.h":

#ifndef CAR_H
#define CAR_H


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

    private:
        static int total;
};

#endif // CAR_H

Veja que declaramos a variável inteira 'total' como estática. Vamos ver a implementação, o 'Car.cpp':

#include "Car.h"

int Car::total = 0;

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

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

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

A primeira coisa que fizemos foi inicializar a variável total com 0, afinal, inicialmente, nenhum objeto foi instanciado.  A função construtora simplesmente incrementa o valor de total, ou seja, cada vez que instanciarmos um objeto, essa variável vai ser incrementada.

E na função destrutora, decrementamos esse variável.

E como ela é estática, esse valor vai representar o número de objetos criados a partir da classe Car. Veja como ficou nossa main.cpp:

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

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

    cout<<"Numero de objetos instanciados: "<< (*ptr1).getTotal() <<endl;

    delete ptr3;

    cout<<"Numero de objetos instanciados: "<< (*ptr1).getTotal() <<endl;

    return 0;
}

Primeiro, criamos três ponteiros do tipo Car. Em seguida, fazemos a alocação dinâmica de memória.
Printamos o resultado após essas 3 alocações. Deletamos o terceiro ponteiro (isso faz com que a função destructor ~Car() seja acionada), então printamos novamente o número de instâncias.

E o resultado é: 

"Numero de objetos instanciados: 3"
"Numero de objetos instanciados: 2"

Note que usamos a função do primeiro objeto, '*ptr1', que criamos, isso prova que a variável 'total' é a mesma, para todos os objetos.


Função estática

Assim como existem as variáveis estáticas, também podemos criar funções estáticas, para uma classe. Porém, elas tem uma característica bem específicas: só podem atuar sobre variáveis estáticas.

Vamos criar a função zero(), que vai zerar a variável 'total'. Nossa classe "Car.h":

#ifndef CAR_H
#define CAR_H

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

    private:
        static int total;
};

#endif // CAR_H

Nossa implementação "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;
}

Por fim, nossa 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<<"Numero de objetos instanciados: "<< (*ptr1).getTotal() <<endl;
    delete ptr3;
    cout<<"Numero de objetos instanciados: "<< (*ptr1).getTotal() <<endl;
    Car::zero();
    cout<<"Numero de objetos instanciados: "<< (*ptr1).getTotal() <<endl;

    return 0;
}

E o resultado é: 

"Numero de objetos instanciados: 3"
"Numero de objetos instanciados: 2"
"Numero de objetos instanciados: 0"

Uma coisa interessante sobre membros estáticos, é que eles existem antes mesmo de qualquer instância da classe ser criada. Assim, sem criar objetos nenhum, você já pode acessar 'total' e 'zero()'.

Por exemplo, você pode pedir um valor ao usuário e usar esse valor para alterar uma variável estática de uma classe, antes mesmo de começar a instanciar objetos dela, e começar a trabalhar com os objetos a partir de um valor previamente determinado pelo usuário.

Nenhum comentário:

Postar um comentário