interessante ressaltar que a criao de novas classes de objetos uma atividade primria da programao orientada a objetos, e a complexidade do programa geralmente escondida nestes objetos. Sendo assim, escrever a funo main() consiste em gerenciar objetos. Um tpico mais complexo sobre criar um tipo definido pelo usurio (ou classe de objetos) a passagem de objetos para, e retorno de objetos de funes. Nesta seo descrita a passagem de parmetros, sendo que dada especial ateno construo de classes complexas que podem ser passadas e retornadas corretamente.
Uma funo comunica-se com o "mundo externo" de duas maneiras: mudando os valores que so globais funo ou atravs de passagem e retorno de valores. A informao pode ser movida da/para funo de duas maneiras: Uma cpia da varivel inteira feita; Somente o endereo da varivel transferido pelos limites.
O primeiro mtodo chamado passagem por valor. J que feita uma cpia do argumento (ou varivel), esta pode ser usada e alterada dentro da funo sem afetar a varivel da qual ela foi gerada. Entretanto, quando uma funo precisa ser capaz de alterar os valores das variveis usadas como argumentos, os parmetros precisam ser explicitamente declarados como tipos ponteiros. Assim, utiliza-se o segundo mtodo que chamado de passagem por nome, quando um ponteiro passado, ou de passagem por referncia, quando referncias so usadas. Em ambos os casos um endereo manipulado.
Os endereos so passados por duas razes. A primeira simplesmente pela eficincia; sabendo-se que a varivel ser somente lida, ento, geralmente mais rpido passar o endereo quando se usam objetos maiores do que um ponteiro. Existe tambm um benefcio adicional em se passar um endereo. No caso de objetos, passa-se o endereo para um objeto inicializado e o tamanho do endereo sempre o mesmo, assim no h problema envolvendo cpia e inicializao.
A segunda razo para passar um endereo manipular fisicamente o objeto ou varivel para o qual o endereo aponta, isto , pode-se alterar uma varivel ou objeto que externo a uma funo. Normalmente, os resultados de uma chamada de funo devem ser expressos pelo valor de retorno da funo, mas existem situaes em que isso no satisfatrio. Por exemplo, a funo pode precisar alterar mais de um objeto. Se os endereos do objeto so passados, a funo pode afetar diretamente qualquer nmero de objetos na funo chamadora.
Na passagem por nome, so explicitamente declarados ponteiros e passados endereos. J passar por referncia o mesmo que declarar um argumento para ser um ponteiro e, ento, passar um endereo. Com referncias, entretanto, o compilador faz todo o trabalho para o usurio: ele fora o endereo a ser passado dentro de uma funo, ainda que o usurio no pegue o endereo explicitamente. Dentro da funo, pode-se manipular os itens como se fossem objetos. Isso um grande avano, uma vez que muitos erros quando se usam bibliotecas da linguagem C, podem ser atribudos confuso sobre como passar um endereo. Como o compilador da linguagem C++ manipula os detalhes, quando se passa argumentos por referncia, muito poucos erros ocorrem. Tambm muito mais eficiente passar um ponteiro do que copiar o objeto inteiro dentro da funo chamada.
Entretanto, existem casos onde preciso uma cpia de um objeto a ser criado dentro da janela da funo. Pode-se necessitar modificar o objeto sem querer que o original seja tocado. Nesses casos, deve-se passar o objeto por valor. Se o compilador passa um int ou float, por exemplo, ele sabe o que fazer: uma cpia Professora Isabel Harb Manssour Linguagem de Programao C++ 26
do dado empurrada na pilha antes que a funo seja chamada. Quando se passa um tipo definido pelo usurio, entretanto, o compilador no tem idia de como manipul-lo.
No caso de uma classe "simples" (nenhum dos dados-membros so ponteiros) onde no foi definido um inicializador de cpia, o compilador recorre a uma cpia bit a bit, que copia todos os bytes da struct do objeto antigo na struct do novo objeto. Porm, se alguns dos membros da classe so ponteiros, uma "cpia mais complexa" usualmente requerida para alocar memria livre e copiar os itens que so apontados [1].
O exemplo abaixo ilustra a passagem por valor e por referncia:
void f (int val, int& ref) { val ++; ref++; }
void g () { int i = 1, j = 1; f(i, j); }
Neste caso, quando "f()" chamada, "val++" incrementa uma cpia local do primeiro argumento, enquanto "ref++" incrementa o segundo argumento. Sendo assim, na funo "g()", "j" incrementado, mas "i" no, pois o primeiro passado por referncia e o segundo por valor.
Se um vetor usado como argumento, um ponteiro para o seu elemento inicial passado. Por exemplo: : int strlen(const char*); void f() { char v[] = "an array"; int i = strlen(v); int j = strlen("Nicholas"); } : Vetores diferem de outros tipos nos quais um vetor no (e no pode ser) passado por valor. O tamanho do vetor no disponvel para a funo chamada [8].
Torna-se importante salientar que se uma expresso especificada em uma declarao de argumentos, essa expresso usada como um argumento default. Todos os argumentos subseqentes devem ter argumentos default fornecidos nessa ou em declaraes prvias desta funo. Um argumento default no pode ser redefinido por uma declarao posterior (ainda que para o mesmo valor). Porm, uma declarao pode acrescentar argumentos default no fornecidos em declaraes anteriores.
Na declarao: ponto (int = 3, int = 4); tem-se uma funo que pode ser chamada com zero, um ou dois argumentos do tipo int. Ela pode ser chamada de qualquer dessas formas: ponto (1, 2); ponto (1); ponto (); As duas ltimas chamadas so equivalentes a "ponto(1,4)" e "ponto(3,4)", respectivamente [2].
Ponteiros tambm podem ser argumentos de funes, apesar disto no ser muito usual em C++, uma vez que existem os parmetros de referncia. Assim sendo, para passar um argumento para uma funo para uso direto, uma instruo deve passar um "endereo" desse argumento para um parmetro do tipo ponteiro.
Professora Isabel Harb Manssour Linguagem de Programao C++ 27
A seguir ser apresentado um exemplo que mostra a diferena entre usar os parmetros por referncia e passar um ponteiro como argumento. Supondo que foi criada a seguinte estrutura para acompanhar as temperaturas baixas e altas: struct temp { float alta; float baixa; } Esta estrutura usada em um programa que faz o acompanhamento das leituras altas e baixas de um termmetro de algum modo ligado ao computador. Uma funo-chave neste programa l a temperatura corrente e modifica o campo apropriado em uma estrutura do tipo "temp" passada por referncia para uma funo. O cdigo fica da seguinte maneira:
if (atual > t.alta) t.alta = atual; else if (atual < t.baixa) t.baixa = atual; } :
Neste exemplo, como o parmetro de "registratemp" passado por referncia, a funo opera diretamente na varivel "atemp". Se o parmetro no tivesse sido declarado com &, a funo operaria apenas sobre uma cpia do valor desse argumento. Com exceo do caracter &, entretanto, as instrues da funo so idnticas, tenha sido o parmetro passado por valor ou por referncia.
No cdigo abaixo, as instrues da funo consideram que "t" um ponteiro e no uma varivel: : resgistratemp(&atemp); : void registratemp (temp *t) { float atual;
pegatempatual(&atual);
if (atual > t->alta) t->alta = atual; else if (atual < t->baixa) t->baixa = atual; } : Neste caso, em vez de usar expresses como "t.alta" e "t.baixa" para fazer referncias aos campos da estrutura, as instrues devem usar o smbolo "->" [4].
importante salientar que quando um objeto passado como um argumento para uma funo, uma cpia desse objeto feita. Alm disso, quando a cpia feita, a funo construtora desse objeto no chamada. No entanto, quando a funo termina, a destrutora da cpia chamada. Se, por alguma razo, o usurio no desejar fazer uma cpia ou no quiser que a funo destrutora seja chamada, basta passar o objeto por referncia. Quando um objeto passado por referncia, nenhuma cpia dele feita. Isso significa que nenhum objeto usado como parmetro e destrudo quando a funo termina, e a destrutora do parmetro no chamada.