O
BJETOS COMOP
ARÂMETROS,
R
ETORNANDOO
BJETOS DEF
UNÇÕES,
F
UNÇÕESA
MIGASA essa altura, já se percebe que objetos podem ser manipulados como se fossem variáveis
comuns. A aula de hoje abordará como a passagem de objetos para funções é realizada. Além
disso, será visto que é possível retornar um objeto de uma função.
A aula de hoje abordará, também, um tipo especial de função, chamada de função amiga,
que mesmo não sendo uma função-membro da classe, pode acessar os atributos da classe como
se a classe pertencesse.
P
ASSAGEM DEO
BJETOS PORV
ALORDa mesma maneira que variáveis eram passadas como parâmetros de funções, objetos
podem ser passados para funções. Observe o exemplo abaixo.
#include <iostream> using namespace std;
class cadastro {
public:
string nome; int idade; };
void print(cadastro aux) {
cout << "Nome: "; cout.width(30);
cout.unsetf(ios::adjustfield); cout.setf(ios::left);
cout << aux.nome;
cout << "Idade: " << aux.idade << endl; }
int main(void) {
cadastro p1;
p1.nome = "Neil Peart"; p1.idade = 60; print(p1);
system("PAUSE"); return 0;
}
Atente para o parâmetro da função print, que imprime na tela os dados do objeto. Essa
chamada é uma chamada por valor, ou seja, o que é passado para a função é uma cópia do objeto
p1, e não o objeto. Existem poucos casos em que uma chamada por valor ocasionará problemas.
Para objetos com construtores e destrutores mais complexos, principalmente aqueles que utilizam
alocação dinâmica ou alocam outros recursos, um estudo mais detalhado sobre alguns problemas
colaterais oriundos da passagem de objetos por valor deve ser realizado utilizando as referências
da disciplina. Para os programas simples com os quais temos trabalhado, no entanto, a passagem
por valor não ocasionará problema algum.
Lembre-se que em uma passagem por valor a função não consegue alterar o objeto
original
Programa 2
. Isso se deve ao fato de que apenas uma cópia do objeto original é passada para a função.
Estude o .
#include <iostream> using namespace std;
class cadastro {
public:
string nome; int idade; };
void f1(cadastro aux) {
aux.idade = 30;
cout << "Na funcao: " << aux.idade << endl; }
int main(void) {
cadastro p1;
p1.nome = "Neil Peart"; p1.idade = 60; f1(p1);
cout << "No programa principal, apos chamada, idade: " << p1.idade << endl; system("PAUSE");
return 0; }
Programa 2 Chamada por valor.
Note que a função não alterou a idade original de Neil Peart.
P
ASSAGEM DEO
BJETOS PORR
EFERÊNCIADa mesma maneira que com variáveis “normais”, as funções podem receber uma
referência ao objeto. Essa passagem pode ser através de um ponteiro ou através de um parâmetro
#include <iostream> using namespace std;
class cadastro {
public:
string nome; int idade; };
void f1(cadastro *aux) {
aux->idade = 30;
cout << "Na funcao: " << aux->idade << endl; }
int main(void) {
cadastro p1;
p1.nome = "Neil Peart"; p1.idade = 60; f1(&p1);
cout << "No programa principal, apos chamada, idade: "; cout << p1.idade << endl;
system("PAUSE"); return 0;
}
Programa 3 Passagem por referência utilizando ponteiro.
Perceba que, no Programa 3 a referência é passada utilizando a abordagem por ponteiros.
Um ponteiro para objeto é muito semelhante a um ponteiro para estrutura. Em ambos os casos,
utiliza-se o operador seta (->).
Lembre-se que, no caso da passagem por referência, quem é passado para a função é o
endereço do objeto. Desse modo, a função passa a ter acesso ao objeto original, e é capaz de
alterar os valores dos atributos do objeto original
Outra maneira de realizar a passagem por referência é utilizando um parâmetro de
referência. Desse modo, evita-se a operação com o operador seta (->) o que torna o código um
pouco mais intuitivo. Porém, novamente, o que é passado para a função é o endereço do objeto. . Cabe aqui uma consideração quanto à
velocidade de execução. A passagem por referência é mais rápida do que a passagem por valor,
uma vez que o programa tem que realizar a cópia de todo o objeto na chamada por valor,
enquanto na chamada utilizando referência, tão somente o endereço do objeto é passado. No
caso de objetos grandes, isso pode poupar muito tempo de execução.
#include <iostream>
using namespace std;
class cadastro {
public:
string nome; int idade; };
void f1(cadastro &aux) //parâmetro de referência {
aux.idade = 30;
cout << "Na funcao: " << aux.idade << endl; }
int main(void) {
cadastro p1;
p1.nome = "Neil Peart"; p1.idade = 60; f1(p1); //não é necessário o &
cout << "No programa principal, apos chamada, idade: "; cout << p1.idade << endl;
system("PAUSE"); return 0;
}
R
ETORNANDO UMO
BJETO DE UMAF
UNÇÃODa mesma maneira que uma variável do tipo int, e.g., é retornada de uma função, um
objeto pode ser retornado. A única diferença é o tipo informado na declaração da função. Analise
com cuidado o Programa 5.
#include <iostream> #include <cstdlib> using namespace std;
int cont;
class cadastro {
public:
string nome; int idade; };
void print(cadastro aux) //imprime {
cout << "Nome: "; cout.width(30);
cout.unsetf(ios::adjustfield); cout.setf(ios::left);
cout << aux.nome << "Idade: " << aux.idade << endl; }
cadastro gera(void) //a função retorna um objeto do tipo cadastro... {
cadastro aux; char str[10];
itoa(cont++, str, 10); //converte cont para uma string (str) aux.nome = "Gerado randomicamente n";
aux.nome.append(str); //adiciona o número do elemento... aux.idade = rand()%120; //gera idade aleatória
return aux; }
int main(void) {
cadastro p1;
srand(time(NULL)); cont = 0;
do {
p1 = gera(); print(p1); }while(cont < 15); system("PAUSE"); return 0;
}
Programa 5 Retornando um objeto.
F
UNÇÕESA
MIGASNa linguagem C++ existe um tipo especial de função que, mesmo sem ser uma função
membro de uma classe, pode ter acesso aos atributos privados da classe. A esse função deu-se o
nome de função amiga da classe.
Para definir uma função amiga, basta declará-la na classe adicionando, antes da função, a
palavra chave friend. Essa palavra informa ao compilador que a função é uma função amiga e
que pode acessar todos os atributos da classe.
#include <iostream> #include <cstdlib> using namespace std;
class exemplo {
int n1;
float n2; //privados por padrão
public:
friend int testa(exemplo aux);
void imprime(void) { cout << n1 << " " << n2 << endl; } exemplo(int a, float b) { n1 = a; n2 = b; }
};
int testa(exemplo aux) {
if(aux.n1 > aux.n2) return 1; //por ser amiga, a função tem
if(aux.n1 == aux.n2) return 0; //livre acesso aos atributos
if(aux.n1 < aux.n2) return -1; //mesmo sendo privados.
}
int main(void) {
exemplo e1(1,1.00);
cout.unsetf(ios::fixed); cout.setf(ios::scientific); cout.precision(4);
e1.imprime();
if(!testa(e1)) cout << "Sao iguais\n"; system("PAUSE");
return 0; }
Programa 6 Função amiga.
Observe que a função, mesmo não sendo membro da classe (perceba que o operador
resolução de escopo não está presente na implementação da função), possui acesso livre aos
atributos n1 e n2.
Exercício 1 Crie uma função lógica que receba dois objetos de uma classe qualquer (crie uma
classe) e compara todos os atributos dos objetos, retornando verdadeiro se os dois objetos forem idênticos.
Exercício 2 Crie duas funções para realizar a leitura dos atributos da classe transistor do exercício 2