Grátis
169 pág.

Denunciar
Pré-visualização | Página 30 de 50
de funções. Isto significa que, caso a chamada da função omita algum parâmetro, a função pode usar o default previamente definido. A forma de definir valores default é explicitá-los na declaração da função, omitindo ou não o nome das variáveis. Uma vez definidos na declaração, os valores default não devem ser repetidos na definição, pois o compilador reconhece nisto uma duplicidade de default. O exemplo a seguir apresenta a declaração do default de uma função e chamadas por ele viabilizadas: unsigned int pares(int, int = 0); // protótipo int n1 = pares(20,3); int n2 = pares(20); Se o primeiro argumento foi omitido, todos os subsequentes deverão ser omitidos. Se o segundo argumento for omitido, todos os subsequentes deverão ser omitidos e assim por diante. Podemos escrever funções que tenham parâmetros inicializados com um valor default e parâmetros não-inicializados, mas após a primeira inicialização todos os parâmetros seguintes devem ser inicializados. Exemplo: void linha( int n = 20, char ch, int cor); // Declaração inválida void linha(int n, char ch = ‘*’, int cor = 0); // Declaração válida. Curso de Linguagem Computacional C/C++ ________________________________________________________________________________________________ Sistemas Industriais Inteligentes – DAS – CTC – UFSC 96 13.5.2 Sobrecarga de Funções Sobrecarregar funções significa criar uma família de funções com o mesmo nome, mas com a lista de parâmetros diferentes. Funções sobrecarregadas devem ter a lista de parâmetros diferentes ou em número ou em tipo. Quando a função é chamada, é a lista de parâmetros passada para ela que permite ao sistema identificar qual é o código adequado. Por exemplo, podemos definir a família de funções abaixo, lembrando que devemos definir cada função como se fosse única: int cubo(int n); float cubo(float n); double cubo(double n); 13.5.3 Funções Inline A palavra-chave inline, quando colocada como primeiro elemento do cabeçalho da definição de uma função, causa a inserção de uma nova cópia da função em todo lugar onde ela é chamada. inline int cubo(int n); A definição de uma função inline deve preceder a primeira chamada a ela. Ou seja, se a função for chamada em main(), seu código deve ser escrito antes de main(). Isto é necessário, pois o compilador deve conhecer de antemão o código da função para poder inseri-la dentro do programa. Uma função é um código presente uma única vez no programa que pode ser executado muitas vezes. Assim, um dos motivos para escrever funções é o de poupar memória. Quando uma função é pequena e queremos aumentar a velocidade de execução de um programa, tranformamo-la em inline. 13.5.4 Operador Unário de Referência: & O operador de referência cria outro nome para uma variável já criada. As instruções: int n; int & n1 = n; // toda referência deve ser inicializada informam que n1 é outro nome para n. Toda operação em qualquer dos nomes tem o mesmo resultado. Uma referência não é uma cópia da variável a quem se refere. É a mesma variável sob nomes diferentes. O uso mais importante para referências é ao passar argumentos para funções. Os exemplos de argumentos de funções vistos até o momento são passados por valor ou por ponteiros. Quando argumentos são passados por valor, a função chamada cria novas variáveis do mesmo tipo dos argumentos e copia nelas o valor dos argumentos passados. Desta forma, a função não tem acesso às variáveis originais da função que chamou, portanto não as pode modificar. A principal vantagem da passagem por referência é a de que a função pode acessar as variáveis da função que chamou. Além desse benefício, este mecanismo possibilita que uma função retorne mais de um valor para a função que chama. Os valores a serem retornados são colocados em referências de variáveis da função chamadora. A passagem por referência possui as vantagens da passagem de parâmetros por ponteiros, i.e., acesso direto à variável fornecida como parâmetro. No entanto, ponteiros exigem que tenhamos cuidado ao manipular o endereço das variáveis para não causar um erro fatal de acesso a memória. Este tipo de preocupação já não existe com passagem por referência, pois não lidamos com o endereço da variável mas sim com uma cópia do seu nome. Funções que recebem argumentos por referência utilizam o operador & somente na definição do tipo do argumento e possuem chamadas idênticas a uma função normal. Exemplo: Curso de Linguagem Computacional C/C++ ________________________________________________________________________________________________ Sistemas Industriais Inteligentes – DAS – CTC – UFSC 97 void reajusta( float& num, float& p = 15 ); // Protótipo int main(int argc, char* argv[]) { float preco = 10; reajusta( preco, 5); // Chamada a função reajusta( preco); // Chamada usando o argumento default return 0; } void reajusta( float& num, float& p ) //Definição { num *= p; } 13.6 Alocação Dinâmica de Memória em C++ A alocação dinâmica de memória em C++ é feita com os operadores new (alocação) e delete (liberação), análogos às funções malloc() e free(). Em C++, o gerenciamento dinâmico de memória é tão relevante que as palavras new e delete foram incorporadas a linguagem. A diferença básica entre os operadores C++ e C está na confiabilidade e facilidade de uso. Por exemplo, o tamanho do tipo para o qual se pede memória deve ser informado à malloc(), enquanto que new descobre esse tamanho automaticamente. Declaração C: Declaração C++ double *ptr; double *ptr; prt = (double*)malloc(sizeof(double)); ptr = new double; C++ já fornece um ponteiro para o tipo de dado fornecido, não necessitando das conversões de tipo requeridas por malloc(). Outra vantagem é que C++ define quanto de memória é necessário, diminuindo o risco que o programador faça algum tipo de erro. Uma vantagem importante é que os operadores new e delete podem ser sobrecarregados (reimplementados) para um tipo de dado criado pelo programador. Isto permite que o programador controle como será alocada memória para o seu tipo de dado. Sempre que uma memória alocada para uma variável não for mais necessária, devemos liberá-la utilizando o operador delete. As formas de utilizar o operador new (alocação de memória) e delete (liberação de memória) são: a) como operador ou função ptr_tipo = new tipo; ptr_tipo = new(tipo); int * ptr1 = new int; int * ptr2 = new(int); delete ptr1; delete ptr2; b) alocação e liberação de matrizes ptr_tipo = new tipo[tamanho_matriz]; int * ptr3 = new int[10]; delete[] ptr3; // ou, explicitamente: delete[10] ptr3; c) alocação e liberação de matrizes de ponteiros ptr_ptr_tipo = new tipo * [tamanho_matriz]; int * * ptr4 = new int * [10]; delete[] ptr4; // ou, explicitamente: delete[10] ptr4; Curso de Linguagem Computacional C/C++ ________________________________________________________________________________________________ Sistemas Industriais Inteligentes – DAS – CTC – UFSC 98 Analogamente ao que ocorre a função malloc() do C, o operador new retorna um ponteiro nulo quando a memória disponível é insuficiente. Assim, devemos sempre verificar se a alocação foi realizada com sucesso, ou seja, se o ponteiro contém um endereço diferente de zero. 13.7 Exercícios 13.1 Escreva um programa que desenhe na tela o gráfico da função y = cos(x) + x/2. Utilize cout e cin para isto. Desenhe todos os elementos do gráfico: título, legenda, linhas horizontal e vertical e numeração. Marque os pontos pertencentes ao gráfico com o caracter (*). 13.2 Crie um programa para fazer cadastro de doentes em um hospital. Utilize estruturas e funções, com passagem de parâmetros por referência. O programa deve apenas adquirir os dados e quando o usuário terminar o cadastro, o programa deve imprimir na tela todas as fichas feitas. 13.3 Modifique o programa acima para utilizar agora a alocação dinâmica em C++ e