Stoa :: C/C++ :: Blog :: Introdução à programação em C/C++ - parte 5

novembro 28, 2007

user icon

Nesta parte da introdução discutiremos superficialmente um dos mais importantes recursos da linguagem C++, mas que não existe em C. Trata-se das classes.

 

Uma classe nada mais é do que uma estrutura que tem como partes tanto dados quanto funções. As classes são um recurso importante pois "encapsulam" as informações e as funcionalidades a respeito de uma certa "coisa" de maneira organizada e reusável.

 

Uma classe define algo que poderia ser descrito como sendo um padrão ou um plano: aquilo que uma classe descreve pode ser produzido muitas vezes, da mesma maneira que uma planta de um edifício pode corresponder a muitas construções, ou o desenho de uma máquina pode servir de base para a produção de muitas máquinas iguais. O desenho ou a planta é chamado de classe, e suas "realizações" são chamadas de objetos.

 

Agora você deve ser capaz de entender o que quer dizer a expressão "objetos são instâncias de classes". Essa expressão quer dizer que assim como várias casas iguais são feitas a partir de uma mesma planta, vários objetos iguais são feitos a partir de uma mesma classe. O verbo "instanciar" é utilizado em programês para indicar a instrução do programa que cria um objeto a partir de uma classe.

 

Por exemplo:

 

carro fusca;

 

Nessa instrução (que é uma "criação de instância de classe", em programês), um objeto de classe "carro" é criado e a esse objeto é atribuído o nome "fusca". Que dados e que funções tem o objeto fusca depende de quais são os membros da classe carro.

 

Por exemplo:

 

classe carro {

    int velocidade_maxima;

    char fabricante[30];

    void ir_ate_usp();

    void voltar_para_casa(); };

 

Neste caso, a classe carro tem como membros duas variáveis e duas funções. Portanto cada objeto de tipo carro terá essas duas variáveis e essas duas funções. Mas veja bem: cada variável de um objeto é única daquele objeto.

 

Por exemplo:

 

carro fusca;

fusca.velocidade_maxima = 90;

carro porsche;

porsche.velocidade_maxima = 290;

if (fusca.velocidade_maxima == porsche.velocidade_maxima)

    printf("Compre esse fusca!!!\n");

 

Neste exemplo, a instrução printf nunca será executada. Por que? O que este exemplo mostra é que a variável "velocidade_maxima" do objeto fusca é diferente da variável "velocidade_maxima" do objeto porsche. Isso é equivalente a dizer que se a classe fosse a planta de uma casa, e cada objeto uma casa realmente construída a partir daquela planta, a cozinha da casa A é diferente da cozinha da casa B, ainda que em ambas haja canos, ralos, torneiras, pias, etc, nas mesmas posições relativas. Em outras palavras, quando dizemos que objetos de uma mesma classe têm os mesmos membros, queremos dizer que cada objeto de uma mesma classe possui o mesmo formato, mas não que eles tenham a mesma variável com o mesmo conteúdo.

 

Apenas para reforçar (desculpem a insistência, mas é um erro muito comum!): os objetos de uma mesma classe são como os animais pertencentes a uma mesma espécie. Assim como dizemos que todo elefante tem tromba, dizemos que todo objeto da classe carro tem a variável velocidade_maxima. Mas cada elefante tem sua própria tromba, assim como cada objeto carro tem sua propria variável velocidade_maxima! Portanto os membros da classe são como os atributos de uma espécie: ter tromba, ser mamífero, ter orelhas grandes, etc. Mas cada elefante terá sua própria tromba de comprimento específico, será filhote e/ou pai/mãe de outros elefantes específicos, sua orelha poderá abana-lo em momentos diferentes daqueles em que um outro elefante irá abanar-se, etc.

 

Vamos agora explicar brevemente a utilidade de termos funções encapsuladas dentro de classes. Antes de mais nada, que fique bem claro que aquilo que é feito com classes pode ser feito com programação "normal" sem classes (que é geralmente chamada de programação estruturada*). O que ocorre é que certas coisas que podem ser feitas de maneira muito simples através de classes só podem ser feitas estruturadamente com muitas e complexas linhas de código.

 

Como dissemos antes, uma classe pode ter como membros tanto variáveis quanto funções.

 

Por exemplo:

 

classe investidor {

    float grana;

    float risco_aceitavel;

    bool grana_na_poupanca = false;

    void investir_poupanca(float juros);

    void investir_bolsa(float indice); };

 

Neste exemplo, podemos escrever uma função que, recebendo os índices de juros de poupança e o valor da expectativa de rendimentos da bolsa escolhe qual o melhor investimento a ser feito de acordo com a aceitação de riscos de cada investidor. Neste caso:

 

void fazer_investimentos(investidor clientes[], int nclientes, float juros_poupanca, float expectativa_bolsa, float risco_bolsa) {

for (int i = 0; i < nclientes; i++)

    if (clientes[i].grana_na_poupanca == false)

        if (clientes[i].risco_aceitavel <= risco_bolsa)

            clientes[i].investir_bolsa();

        else {

            clientes[i].investir_poupanca(juros_poupanca);

            clientes[i].grana_na_poupanca = true; } }

 

Esta função irá percorrer um vetor de clientes (note que esse vetor tem o tipo "investidor") e, para cada cliente, caso seu dinheiro não esteja investido na poupanca, irá verificar se o risco de investir na bolsa é aceitável e, caso seja, irá investir na bolsa. Caso o risco seja alto demais, irá investir na poupança. Para que o exemplo seja completo, seria necessário guardar a data do investimento na poupança, e verificar todo dia se algum cliente já completou um mês com seu dinheiro na poupança, e se portanto esse dinheiro já está liberado para ser investido na bolsa novamente.

 

A chamada a "investir na poupança" pode ser mais ou menos assim:

 

void investidor::investir_poupanca(float juros) {

    grana = grana * (1 + juros/100); }

 

O cabeçalho dessa função é ligeiramente diferente daquele que seria o cabeçalho da função caso ela não fosse membro de uma classe, mas isso se restringe à declaração de escopo (investidor::). Isso é um detalhe que exploraremos quando falarmos da sintaxe das classes. O importante é notar que na função investir_poupanca nós utilizamos a variável grana sem declará-la, ou seja, nós utilizamos a variável grana do objeto a partir do qual chamamos a função-membro.

 

Ou seja, se eu tiver um objeto investidor chamado bancoIrreal:

 

investidor bancoIrreal;

bancoIrreal.grana = 1000;

j = 0.5;

 

e chamar a função investir_poupanca da seguinte maneira:

 

bancoIrreal.investir_poupanca(j);

 

Essa função irá utilizar a variável grana definida para o objeto bancoIrreal, sem precisar declará-la. Isso decorre do fato de que os membros de uma classe são visíveis para todos os membros dessa classe.

 

A visibilidade de um membro é controlável em C++. Mas esse já é um tópico que deixaremos para uma discussão futura das classes. Basta, no momento, saber que o padrão é que o membro sejá visível, ou, em programês, público. (Ele também poderia ser privado ou restrito).

 

* A programação estruturada é toda programação na qual se utilizam estruturas como funções ou procedimentos, mas não classes ou objetos. Portanto C é uma linguagem estruturada, enquanto que C++ pode ser utilizada estruturadamente ou orientada a objetos.

Palavras-chave: classes, objetos

Postado por Renato Callado Borges em C/C++

Você deve entrar no sistema para escrever um comentário.

Termo de Responsabilidade

Todo o conteúdo desta página é de inteira responsabilidade do usuário. O Stoa, assim como a Universidade de São Paulo, não necessariamente corroboram as opiniões aqui contidas.