Linguagem de Programação II Carlos Oberdan Rolim Ciência da Computação Sistemas de...

30
Linguagem de Programação II Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação

Transcript of Linguagem de Programação II Carlos Oberdan Rolim Ciência da Computação Sistemas de...

Page 1: Linguagem de Programação II Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação.

Linguagem de Programação II

Carlos Oberdan Rolim

Ciência da ComputaçãoSistemas de Informação

Page 2: Linguagem de Programação II Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação.

ClassesParte II

Page 3: Linguagem de Programação II Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação.

Funções, métodos e classes friends

Inconveniente gerado pelo uso de private

C++ proporciona uma forma de contorno através de friends que podem ser funções, classes e métodos

Page 4: Linguagem de Programação II Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação.

Funções friends

Função friend é uma função nãomembro (não pertence a uma classe) que permite acesso aos membros da seção private de uma classe

Quando uma função torna-se friend ela terá os mesmos privilégios de acesso que um método da classe tem

As funções friend são um pouco diferentes de métodos

Um método é chamado por um objeto específico

Uma função friend por não ser membro de classes, não pode ser chamada por um objeto. Ao contrário, deverá receber um objeto como argumento, sobre o qual atuará

Page 5: Linguagem de Programação II Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação.

#include <iostream>#include <cstring>#include <conio.h>

using namespace std;

class esposa; // declaracao antecipada

class marido { public: marido(char *, float); ~marido(); friend void exibe(marido, esposa); private: char nome1[10]; float salario1;};

class esposa { public: esposa(char *, float); ~esposa(); friend void exibe(marido, esposa); private: char nome2[10]; float salario2;};

void exibe (marido h1, esposa h2){ cout << “Nome” << h1.nome1; cout << “Salario” << h1.salario;

cout << “Nome” << h2.nome2; cout << “Salario” << h2.salario2;

}

int main(){

marido homem(“joao”,2000,00);esposa mulher(“Maria”, 3000,00);

exibe(homem, mulher);

getch();

return 0;

}

Page 6: Linguagem de Programação II Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação.

Informações adicionais

Declaração antecipada (forward declaration) diz ao compilador que a classe está definida mais a frente. É necessária por causa do protótipo friend void exibe(marido, esposa) que faz referência a classe esposa que ainda não existe

Como a função recebe um objeto como argumento o protótipo de função foi declarada como friend exibe(homem, mulher); (lembrando que no protótipo não preciso informar nome após o tipo)

O cabeçalho de definição da função friend, ao contrário do protótipo, não possui a palavra friend

Como não pertence a classe não possui o operador de resolução de escopo ::

A passagem de argumentos pode ser feita por valor, por referência ou por endereço.(Lembrando: a passagem de argumentos a uma função friend pode ser feita por endereço e por referência são mais rápidas e ocupam menos espaço em memória que por valor)

Passagem por endereço utiliza ponteiros e implica no uso do operador -> cout << “Nome” << h1->nome1;

Page 7: Linguagem de Programação II Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação.

Classes friend

É uma classe cujos métodos podem acessar os membros das seções private e protected de outra classe.

Quando uma classe é chamada como friend todos os seus métodos são entendidos como friends

Mas é possível indicar quais métodos de uma classe serão amigos de uma outra classe

Para indicar que uma classe é amiga de outra escreve-se a expressão friend class antes do nome da classe amiga, na declaração da primeira classe

Page 8: Linguagem de Programação II Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação.

class carro { public: carro(char *, int, char *); void exibe(); friend class fcarro; private: char marca [12]; char modelo [7]; int anofab;

};

class fcarro{ public: void altera(carro &);};

carro :: carro(char * m1, int a, char * m2){ strcpy(marca, m); strcpy(modelo, m2); anofab = a;} ... Implementação do exibe ...

// Método da classe amiga fcarro void altera( carro & c){ strcpy(c.marca, “Ford”); strcpy(c.modelo, “Focus”); c.anofab = 2008;

}

int main(){

carro carro1(“GM”,2000,”Corsa”);

fcarro fcarro1;

// Passagem do argumento por //por referencia pois altera as // variaveis-membro da classe carrofcarro1.altera(carro1);

getch();

return 0;

}

Page 9: Linguagem de Programação II Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação.

Métodos friend

É uma classe cujos métodos podem acessar os membros das seções private e protected de outra classe. Quando uma classe é chamada como friend todos os seus métodos são entendidos como friends

Há situações em que nem todos os métodos precisam ser friends, assim,seleciona-se os métodos da classe friend que irão acessar as seções private e protected da classe original:os métodos friends

Para declarar um método friend, declare o seu protótipo na classe original, iniciando-se pela palavra friend

Page 10: Linguagem de Programação II Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação.

class fcarro; // declaracao antecipada class carro { public: carro(char *, int, char *); void exibe(); friend void fcarro::altera(carro &); private: char marca [12]; char modelo [7]; int anofab;

};

class fcarro{ public: void altera(carro &);};

carro :: carro(char * m1, int a, char * m2){ strcpy(marca, m); strcpy(modelo, m2); anofab = a;} ... Implementação do exibe ...

// Método da classe amiga fcarro void altera( carro & c){ strcpy(c.marca, “Ford”); strcpy(c.modelo, “Focus”); c.anofab = 2008;

}

int main(){

carro carro1(“GM”,2000,”Corsa”);

fcarro fcarro1;

// Passagem do argumento por //por referencia pois altera as // variaveis-membro da classe carrofcarro1.altera(carro1);

getch();

return 0;

}

Page 11: Linguagem de Programação II Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação.

Classes friend recíprocas

Quando uma classe torna-se friend de outra e vice-versa.

Métodos da classeA torna-se friend da classeB, e esta por sua vez torna-se friend da classeA

Page 12: Linguagem de Programação II Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação.

class carro { public: friend class fcarro; carro(char *, int, char *); void exibe_fcarro(fcarro &); private: char marca [12]; char modelo [7]; int anofab;

};

class fcarro{ public: friend class carro; fcarro(float,char); void altera(carro &);};

... Implementação dos métodos das classes ...

int main(){

carro carro1(“GM”,2000,”Corsa”);

fcarro fcarro1(1100., ‘G’);

// Passagem do argumento por //por referencia pois altera as // variaveis-membro da classe carrofcarro1.altera(carro1);

carro1.exibe_fcarro(carro1);

getch();

return 0;

}

Page 13: Linguagem de Programação II Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação.

Sobrecarga de operadores

A sobrecarga de operadores é uma forma de polimorfismo de C++ que permite alterar o significado de seus operadores, cuja idéia é transformar expressões complexas em expressões mais claras e intuitivas.

Por exemplo uma expressão total.soma(p1,p2);pode ser escrita como total = p1 + p2;

C++ possui naturalmente vários operadores sobrecarregados

Compilador com base na quantidade e nos tipos de operandos envolvidos decidirá qual ação executar

Sobrecarga dos tipos básicos também é estentida aos tipos definidos pelos usuários

Page 14: Linguagem de Programação II Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação.

Sobrecarga de operadores

Como sobrecarga de operadores é utilizada com tipos definidos por usuários e como uma classe é um tipo definido pelo usuário, logo é definido por classe

Quando um operador é sobrecarregado em uma classe, o seu significado muda apenas para ela, o restante do programa utilizará o operador com seu significado original

A sobrecarga de operadores utiliza um formato especial de função chamado função operator

operator operador ([argumentos])

operador caractere correspondente ao operador a ser sobrecarregadoargumentos argumentos a serem passados à função, separador por virgula

Page 15: Linguagem de Programação II Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação.

class texto{ public: texto(char *); void exibe(int); void operator –(int); private: static const int comp = 25; char string1[comp];

};

void texto:: exibe(int flag){ if(flag == 1) cout << “String original: ” << string1; else cout << “Substring: ” << string1; }

void texto :: operator –(int qtd){ int k = 0; char str_aux[comp]; while(k < qtd){ str_aux[k] = string1[k] k++; }

str_aux[k] = ‘\o’ ; strcpy(string1,atr_aux);}

texto :: texto(char :* string2){ strcpy(string1, string2);}

int main(){

texto texto1(“Sobrecarga de operad.”); texto1.exibe(); texto1 – 5; texto1.exibe(2);

return 0;

}

Saída:String original: Sobrecarga de operad.Substring: Sobre

Page 16: Linguagem de Programação II Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação.

Critérios para sobrecarga de operadores

A maioria dos operadores pode ser sobrecarregado da mesma maneira. Os operadores com algumas exceções, não precisam ser necessariamente métodos, porém pelo menos um dos operados precisa ser um tipo definido pelo programador

O operador a ser sobrecarregado deve ser um operador válido C++. Por exemplo, o operador $ não pode ser sobrecarregado porque não é um operador válido

O operador a se sobrecarregado deve ter pelo menos um operando que seja um tipo definido pelo programador. Isso elimina a possibilidade do programador sobrecarregar operadores que atuam sobre os tipos predefinidos. Assim, o operador + não pode ser redefinido de forma a subtrair valores em vez de adicioná-los

Page 17: Linguagem de Programação II Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação.

Critérios para sobrecarga de operadores

Um operador não pode ser utilizado de forma a violar as regras originais de sintaxe. Por exemplo, o operador / não pode ser sobrecarregado para utilizar apenas um operando

A precedência dos operadores não pode ser alterada

Operadores que não podem ser sobrecarregados::: . const_cast dynamic_cast reinterpreted_cast static_cast typeid sizeof . * ?:

Operadores que podem ser sobrecarregados apenas utilizando-se metodos:= ( ) [ ] ->

Operadores que não podem se sobrecarregados utilizando-se métodos e funções não-membro+ - * / % ^& | ~ ! = < > += -= *= /= %= ^= &= |= << >> >>= <<= == != <= >= && || ++ -- , ->* -> () [] new delete new[ ] delete[ ]

Page 18: Linguagem de Programação II Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação.

Passagem de objetos como argumentos

Uma função não precisa ser um método ou função friend para utilizar um objeto como argumento

Somente se uma função precisa acessar os membros privados ela terá que ser um método ou função friend

Pode-se passar o objeto por valor, referência e endereço.

Lembrando: Se for passado por endereço utiliza ponteiro e então deve-se utilizar -> para acessar variáveis e métodos

A passagem por referência pode ser mais conveniente que a passagem por endereço, pois mascara a utilização de ponteiros

Page 19: Linguagem de Programação II Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação.

class Carro{ string marca, modelo;

public: Carro(){} Carro(string, string); void exibe(); void altera(Carro);};

Carro :: Carro(string marca, string modelo){ this->marca = marca; this->modelo = modelo;}

void Carro :: exibe(){ cout << "Marca:" << marca << "\n“; cout << "Modelo:" << modelo << "\n“;}

void Carro :: altera( Carro c){ c.marca = "Nova marca“; c.modelo = "Novo modelo“; c.exibe();

}

int main() {

Carro carro("Fiat", "uno");

carro.exibe();

carro.altera(carro);

return 0;

}

Saída

Marca:Fiat

Modelo:uno

Marca:Fiat

Modelo:uno

Marca:Nova marca

Modelo:Novo modelo

Note que o objeto alterado foi o “c” e não o “carro”. Para alterar “carro” deveria ser passado por referencia

Page 20: Linguagem de Programação II Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação.

class Carro{

string marca, modelo;

public:

Carro(){}

Carro(string, string);

void exibe(Carro);

};

Carro :: Carro(string marca, string modelo){

this->marca = marca;

this->modelo = modelo;

}

void Carro :: exibe(Carro c){

cout << "Marca:" << c.marca << "\n";

cout << "Modelo:" << c.modelo << "\n";

}

int main() {

Carro carro("Fiat", "uno");

carro.exibe();

carro.altera(carro);

return 0;

}

Saída

Marca:Fiat

Modelo:uno

Marca:Fiat

Modelo:uno

Marca:Nova marca

Modelo:Novo modelo

Note que o objeto alterado foi o “c” e não o “carro”. Para alterar “carro” deveria ser passado por referencia

Page 21: Linguagem de Programação II Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação.

Retorno de objetos

Da mesma forma que uma função comum um método também pode retornar um valor que pode ser um objeto

Retorno é feito com return normalmente

Page 22: Linguagem de Programação II Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação.

class Numero{

int a, b;

public:

Numero(){} Numero(int, int); Numero inverte(); void mostra();};

Numero :: Numero(int a, int b){ this->a = a; this->b = b;}

Numero Numero :: inverte(){ Numero n; n.a = b; n.b = a; return n;}

void Numero :: mostra(){ cout << "A: " << a << "\n“; cout << "B: " << b << "\n"; }

int main() {

Numero n(1,2), n2;

n.mostra(); n2 = n.inverte(); n2.mostra();

return 0;

}

Saída:A: 1B: 2

A: 2B:1

Page 23: Linguagem de Programação II Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação.

Membros static

Uma variável-membro de classe de memória static é uma variável única, criada para uma dada classe, que fica disponível a todos os objetos que vierem a ser criados.

É utilizada para compartilhar informações entre objetos de uma classe

Existe independente da criação de objetos e permanece na memória durante a execução do programa podendo ser acessada sem a existência de objetos

Quando um objeto é criado ele passa a ter as variáveis-membro da classe que o originou.

Uma variável static não é armazenada nos objetos da classe, mas seu conteúdo fica disponível a todos os objetos que venham a ser criados

A sua utilização implica economia de memória e tempo de processamento

Page 24: Linguagem de Programação II Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação.

class carro { public: carro(char *,char *); private: char modelo [7]; char marca[10] static int cont;

};

int carro :: cont = 0;

carro :: carro(char * marc, char * mod){

strcpy(marca, marc); strcpy(modelo, mod); cont++; cout << “Criado objeto numero” << cont;

}

carro :: ~carro() { cout << “Destruicao do objeto “ << modelo; }

int main(){

carro carro1(“GM”,”Corsa”);carro carro2(“VW”,”Fusca”);

getch();

return 0;

}

Saida:

Criado objeto numero 1Criado objeto numero 2Destruicao do objeto 2Destruicao do objeto 1

Page 25: Linguagem de Programação II Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação.

Métodos static

Um método da classe de memória static não precisa ser chamado por um objeto pois não possui um ponteiro this associado, podendo existir independente da existência de objetos

Page 26: Linguagem de Programação II Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação.

class carro { public: static void exibe(); private: char modelo [7]; char marca[10] static int anofab;

};

int carro :: anofab = 2000;

carro :: exibe(){

cout << “Ano fabricacao ” << anofab;

}

int main(){

// Chama o metodo static exibe() sem// a existencia de objetos da classe carro//Acessa a variavel compartilhada anofab

carro :: exibe();

getch();

return 0;

}

Saida:

Ano fabricacao 2000

Page 27: Linguagem de Programação II Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação.

Classes e alocação dinâmica de memória

A alocação de memória é aquela que ocorre durante a execução de um programa (não em tempo de compilação) e é efetuada pelo operadores new e new[ ]

new utilizado para alocação dinâmica de um valor

Sintaxe: tipo * ponteiro = new tipo;

Exemplo: int * ptr_int = new int; // alocacao de um inteiro

struct st_produto * ptr= new struct st_produto;

ptr -> nome = “joao”; // acesso ao elemento nome

Usar o operador delete para desalocar

delete ptr;

Page 28: Linguagem de Programação II Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação.

Classes e alocação dinâmica de memória

new[ ] utilizado para alocação dinâmica de um array

Sintaxe: tipo * ponteiro = new tipo [ quantidade ];

Exemplo:

cin >> qtd;

int * ptr = new int[qtd]; // alocacao de um vetor

ptr[0] = 1; ptr[1] = 2;

Usar o operador delete[ ] para desalocar

delete ptr[ ];

Page 29: Linguagem de Programação II Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação.

class xstring{ public: void le_nome(); void exibe(); ~xtring(); private: char * texto; };

void xstring :: exibe(){ cout << “Ola “ << texto; }

void xstring :: le_nome() { texto = new char[30]; cin.get(texto,30);}

void xstring :: ~xstring(){

cout << “Obeto “ << texto << “destruido”;

delete [ ] texto;}

int main(){

xtring nome;nome.le_nome();nome.exibe(); return 0;

}

Page 30: Linguagem de Programação II Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação.

Classes e alocação dinâmica de memória

O detalhe mais importante do programa: quando o objeto nome é destruido, o ponteiro texto também o é, mas a memória apontada pelo ponteiro texto continua alocada.

Daí a necessidade de utilizar o destrutor, e nesse, o operador delete [ ] para liberar a referida memória. Observe que o programa funciona sem o operador delete [ ], mas omiti-lo não é uma boa prática de programação