Pretendo, com esta dica, auxiliar no entendimento de:
- O que são funções?
- Porque utilizá-las?
- Como utilizá-las?
- O que são parâmetros? Como passar parâmetros por valor? E por referência?
- Recursividade ou iteratividade? Qual a melhor?
As funções são subprogramas, ou seja, são "pequenos” trechos de códigos especializados em resolver um problema específico, ou seja, ao invés criarmos um programa todo dentro da “int main()1”, o que resulta em código, digamos, meio complicado de entender e dar manutenção.
O que fazemos é adotar o lema: DIVIDIR PARA CONQUISTAR.
Onde, a partir do problema a ser resolvido, o decompomos em partes menores, em vários problemas menores, mais simples de ser resolvidos.
E cada uma destas partes é, como já disse, especialista em resolver um problema específico. Depois disso chamamos cada uma dessas funções conforme for necessário de dentro da função principal.
Acredito que já posso citar aqui, uma grande vantagem das funções: “implemente uma única vez e use indefinidamente”. Ao longo dos exemplos pretendo demonstrar essa expressão de forma mais clara.
É importante ressaltar algumas considerações sobre as funções:
1. Uma função pode, ou não, retornar alguma coisa (caso haja retorno, precisamos definir na sua declaração qual o tipo de retorno terá; ou caso não tenha, dizemos que ela é do tipo “void”).
2. Uma função pode, ou não, receber algum parâmetro (então, caso receba parâmetros, é necessário definir qual o tipo de dado ela espera receber e em qual variável será armazenado; caso não receba nenhum parâmetro, é necessário abrir e fechar parênteses)
3. A sintaxe é:
<tipo de dado><nome_função>(<parametros entrada>){
escopo
return;
}
Onde:
- tipo de dado = Qual o tipo de dado que a função retorna à função que a invocou;
- Nome_função = Nome conforme a “criatividade” do programador;
- parâmetros de entrada = Quais os tipos de dados e parâmetros que a função precisa receber;
- escopo = Aqui é implementado o código que resolverá o problema proposto;
- Return = Aqui será o valor a ser retornado.
Onde “colocar” as funções? Existem duas formas, e nenhuma delas é melhor ou pior do que a outra, o que vai determinar qual delas usar, será a complexidade do código que você está desenvolvendo.
Para trabalhar, de fato, com as funções, são necessários 3 passos, que são:
- protótipo = Apresenta ao compilador o nome do subprograma, o tipo de dado retornado, número, tipo e ordem dos parâmetros de entrada;
- definição = Implementação do subprograma;
- chamada = Utilização da função em alguma expressão ou como um comando.
Deve-se utilizar o protótipo, apenas, quando suas funções forem implementadas após a função principal. Outra recomendação também, é quando o código for muito extenso; ao utilizar protótipo, tem-se uma lista já no início do programa de todas as funções que são utilizadas naquele programa, resultando em organização e manutenibilidade.
Mas o que são estes parâmetros dos quais estou falando? Bom, acredito que já deve ter percebido que tratam-se das variáveis.
Depois de definir os conceitos iniciais, agora já podemos demonstrar alguns exemplos na prática.
Exemplo 1
O código abaixo, apenas solicita um número do usuário e passa este valor para que uma função calcule uma potenciação.
Exemplo 2
O programa abaixo, solicita três valores ao usuário e utiliza uma função para retornar o maior deles. Na sequência, a função principal imprime o resultado.
Exemplo 3
O programa solicita um número e calcula seu fatorial de forma recursiva. Novamente destaco que, a função principal solicita tal número e o repassa a uma função especialista em calcular fatorial. Na sequência, esta função devolve o valor para a função que a chamou.
* Nota: Exemplo 3.1 - Conforme código abaixo, é possível calcular o fatorial de forma iterativa também.
Portanto, decidir quando deve ser utilizado recursividade, ou iteratividade, é uma questão que deve ser muito bem analisada, afinal, a recursividade consome muita memória.
Até agora, toda a passagem de parâmetros foi feita por valor ou por cópia, o que significa que nosso código trabalha com duas variáveis locais: uma na função principal e outra na função especialista. No entanto, é óbvio que apesar de terem nomes diferentes, precisam ser obrigatoriamente do mesmo tipo de dado.
Porém, existe outra forma de fazermos a passagem de parâmetros, esta forma chama-se passagem por referência, que significa que passaremos o endereço de memória para a função especialista.
Esta, por sua vez, efetuará os cálculos com tais valores contidos naquela posição de memória, e em seguida, irá sobrescrevê-los com o resultado.
Matrizes e vetores são sempre passados por referência.
Exemplo 4
O programa abaixo, ilustra uma passagem por referência. O usuário deve informar quantos minutos passaram-se desde as 00:00h até determinado momento, e o programa devolverá aquele resultado no formato: hh:mm
Espero que tenha conseguido deixar claro, do poder e praticidade que as funções podem nos fornecer. Por isso, disse no início, que implemente uma vez, use indefinidamente.
Também citei a questão do protótipo, porém, como os exemplos citados são de programas simples com poucas linhas, optei por implementar minhas funções sempre antes do
int main, portanto, não foi necessário usar os protótipos.
Exemplo 4.1
O código abaixo, é uma repetição do exemplo anterior, porém utilizando protótipo.
Minha intenção com esta dica, não é esgotar o assunto, mas apenas poder contribuir aos iniciantes de programação em
C++, assim como eu.
Segue um link muito importante para nós, por hora aspirantes a programador, e também para os programadores mais experientes: