Técnicas de Programação: Programação Orientada a Objeto PROF. PROTÁSIO DEE-UFPB
Classes e Objetos Classe É uma estrutura de dados que pode conter: Objeto Dados, e Funções. É uma instância de uma classe. 2 Pode-se fazer a seguinte analogia em termos de variáveis: Uma classe poderia ser um tipo de dado int, char,... Um objeto pode ser uma variável int a, char x,...
Declaração de classes Classes são declaradas pela palavra-chave class 3 class nome_da_classe{ Especificador_de_acesso_1: membro1; Ξ Especificador_de_acesso_2: membroa; Ξ ; nome_da_classe É um identificador válido para a classe. Especificador_de_acesso private: Membros privados podem ser acessados somente por membros da mesma classe. Membros públicos podem ser acessados em qualquer escopo em que a classe é visível.
Declaração de classes Classes são declaradas pela palavra-chave class 4 class nome_da_classe{ Especificador_de_acesso_1: membro1; Ξ Especificador_de_acesso_2: membroa; Ξ ; Exemplo: private: void setar_valores (int, int); int area (void); ; Membros da Classe
Declaração de classes Por padrão, todos os membros declarados em um especificador de acesso são privados Assim, 5 private: void setar_valores (int, int); int area (void); ; ; void setar_valores (int, int); int area (void);
Declaração de classes A classe Retangulo contém 4 membros: x e y: dados-membros setar_valores e area: funções-membros Como declarado, x e y são privados, assim só podem ser acessados pelas funções-membros. Como declarado, as funções-membros podem ser acessadas externamente. 6 ; void setar_valores (int, int); int area (void);
Criando (instanciando) um objeto Abaixo tem-se um exemplo em que o objeto Ret é instanciado (criado) 7 ; void setar_valores (int, int); int area (void); Retangulo Ret;
Criando (instanciando) um objeto Abaixo tem-se um outro meio para instanciar o objeto Retang 8 void setar_valores (int, int); int area (void); Ret;
Usando Objetos #include <iostream> using namespace std; 9 void setar_valores (int, int); int area () {return (x*y); ; Operador de Resolução de Escopo void Retangulo :: setar_valores (int a, int b) { x = a; y = b; int main () { Retangulo Ret; Ret.setar_valores(3, 4); cout << Area = " << Ret.area(); return 0;
#include <iostream> using namespace std; 10 void setar_valores (int, int); int area () {return (x*y); ; void Retangulo :: setar_valores (int a, int b) { x = a; y = b; int main () { Retangulo Ret; Ret.setar_valores(3, 4); cout << Area = " << Ret.area(); cout << x = " << x << y = " << y; return 0; Imprimindo o valores de x e y Que aconteceu? Por que? x e y não são variáveis no escopo de main
#include <iostream> using namespace std; void setar_valores (int, int); int area () {return (x*y); ; void Retangulo :: setar_valores (int a, int b) { x = a; y = b; int main () { Retangulo Ret; Ret.setar_valores(3, 4); cout << Area = " << Ret.area(); cout << x = " << Ret.x << y = " << Ret.y; return 0; Imprimindo o valores de x e y Que aconteceu? Por que? x e y são variáveis no escopo de Retang, mas são privadas 11
#include <iostream> using namespace std; 12 void setar_valores (int, int); int area () {return (x*y); void mostrar () { cout << x = " << x << y = " << y; ; void Retangulo :: setar_valores (int a, int b) { x = a; y = b; int main () { Retangulo Ret; Ret.setar_valores(3, 4); cout << Area = " << Ret.area(); Ret.mostrar (); return 0; Imprimindo o valores de x e y Que aconteceu?
#include <iostream> using namespace std; void setar_valores (int, int); int area () {return (x*y); void mostrar () { cout << x = " << x << y = " << y; ; O que é possível fazer para x e y serem acessados pelo main? Tornar x e y públicos 13 void Retangulo :: setar_valores (int a, int b) { x = a; y = b; int main () { Retangulo Ret; Ret.setar_valores(3, 4); cout << Area = " << Ret.area(); Ret.mostrar (); return 0;
#include <iostream> using namespace std; void setar_valores (int, int); int area () {return (x*y); void mostrar () { cout << x = " << x << y = " << y; ; O que é possível fazer para x e y serem acessados pelo main? Tornar x e y públicos 14 void Retangulo :: setar_valores (int a, int b) { x = a; y = b; int main () { Retangulo Ret; Ret.setar_valores(3, 4); cout << Area = " << Ret.area(); cout << x = " << Ret.x << y = " << Ret.y; return 0;
Usando Objetos Desvantagens de tornar dados públicos: Os dados ficam desprotegidos Em geral, ter acesso aos dados, podem causar problemas de: Acesso não permitido 15 Encapsulamento Com os dados-membros desprotegidos, o objeto perde sua capacidade de encapsulamento Consistência Conversão incorreta de tipos de dados A melhor forma de acessar dados-membros é através de funções de: Set: setar os valores dos dados-membros Get: pegar os valores dos dados-membros
#include <iostream> using namespace std; 16 void setar_valores (int, int); int getx () {return x; int gety () {return y; int area () {return (x*y); ; void Retangulo :: setar_valores (int a, int b) { x = a; y = b; int main () { Retangulo Ret; Ret.setar_valores(3, 4); cout << Area = " << Ret.area(); cout << x = " << Ret.getX() << y = " << Ret.getY(); return 0;
Exercício Considerando o programa anterior, crie 2 objetos da classe Retangulo, receba seus valores de x e y pelo teclado e mostre as área na tela. 17
Ponteiros para objetos Suponha a classe Retangulo, o comando a seguir cria um ponteiro a um objeto desta classe: Retangulo *Ret2; 18 Usa-se o operador seta para acessar o objeto Ret2->setar_valores(3, 4); cout << Area = " << Ret2->area();
#include <iostream> using namespace std; 19 void setar_valores (int a, int b) { x = a; y = b; int area () {return (x*y); ; int main () { Retangulo Ret;// cria um objeto Retangulo *Ret2;// cria um ponteiro para objeto Ret2 = &Ret;// Faz com que o ponteiro Ret2 aponte para Ret Ret2->setar_valores(3, 4); cout << "Area = " << Ret2->area(); return 0;
Exercício Crie uma classe Circulo e elabore funções desta classe para calcular sua área e seu perímetro. Após crie um objeto dessa classe e solicite ao usuário o valor do raio e mostre a área e perímetro. Acesse as funções através de ponteiros. 20
Funções Construtoras As funções construtoras são chamadas na criação de um objeto e serve para: Inicializar variáveis-membros, Alocar memória dinamicamente, e Evitar o uso de valores inesperados. As funções construtoras, um tipo de função especial de uma classe, são automaticamente chamadas quando um novo objeto é criado. Uma função construtora: Tem o mesmo nome da classe E não deve ter nenhum tipo de retorno (nem mesmo void) 21
#include <iostream> using namespace std; Retangulo (int a, int b); int area () {return (x*y); ; // Função construtora da classe Retangulo Retangulo::Retangulo (int a, int b) { x = a; y = b; Protótipo da função construtora 22 int main () { Retangulo Ret(3,4);// cria um objeto Retangulo Ret2(10,2);// cria um objeto cout << "Area = " << Ret.area() << endl; cout << "Area = " << Ret2.area() << endl; return 0;
Funções Destrutoras Fazem o oposto da funções construtoras São automaticamente chamadas quando um objeto é destruido: O escopo do objeto é finalizado Exemplo: um objeto é definido localmente dentro de uma função e a função termina O objeto é alocado dinamicamente na memória e é usado um operador de deleção do objeto O destrutor tem o mesmo nome da classe, mas: é precedido de ~ Não retorna nenhum tipo 23
int main () { Retangulo Ret(3,4), Ret2(10,2);// cria os objetos Ret e Ret2 cout << "Area = " << Ret.area() << endl; cout << "Area = " << Ret2.area() << endl; return 0; #include <iostream> using namespace std; int *x, *y; Retangulo (int a, int b); ~Retangulo (); int area () {return (*x) * (*y); ; Protótipo da função destrutora 24 // Função construtora da classe Retangulo Retangulo::Retangulo (int a, int b) { x = new int; // new é um operador para alocar dinamicamente memória para o tipo //especificado, new retorna um PONTEIRO y = new int; *x = a; *y = b; // Função destrutora da classe Retangulo Retangulo::~Retangulo () { delete x;// delete é um operador que deleta a memória alocada para x delete y;
Sobrecarga de construtores Em C++, as funções podem ser sobrecarregadas Sobrecarga significa: Uma mesma função pode realiza operações específicas dependendo do tipo e da quantidade de parâmetros: Exemplo: int soma(int a, int b); float soma(float a, float b); As funções construtoras também podem ser sobrecarregadas 25
#include <iostream> using namespace std; int main () { Retangulo Ret, Ret2(10,2); cout << "Area = " << Ret.area() << endl; cout << "Area = " << Ret2.area() << endl; return 0; Retangulo (); Retangulo (int a, int b); int area () {return x * y; ; 26 Retangulo::Retangulo (int a, int b) { x = a; y = b; Retangulo::Retangulo () { x = 5; y = 5;
Exercício Faça um programa que solicite ao usuário se ele que criar objetos Retângulos ou Circulos, crie arrays de objetos dinamicamente (de acordo com a quantidade de objetos que o usuário desejar) e mostre os resultados das áreas na tela.
Arrays de objetos criados dinamicamente #include <iostream> using namespace std; 28 Retangulo (){x = 5;y = 5; // Função Construtora int area () {return x * y; ; int main () { int i; cout << "Quantos objetos retangulo deseja criar?" << endl; cin >> i; Retangulo *Ret= new Retangulo[i]; for (int j = 0; j < i; j++) cout << "Area" << "[" << j << "] = " << Ret[j].area() << endl; delete[] Ret; return 0;
Arrays de objetos Exemplo 29 Retangulo () {x = 5;y = 5;; // Função Construtora não explícita Retangulo (int a, int b) {x = a; y = b; // Função Construtora explícita Só podem ser criados sem fornecer um construtor explícito Retangulo *Ret= new Retangulo[20]; Não existe maneira de especificar argumentos explícitos para um construtor em uma declaração de array Retangulo *Ret= new Retangulo(1,4)[20];
Arrays de objetos (e se for necessário inicializar cada objeto?) 30 #include <iostream> using namespace std; Retangulo (){cin >> x; cin >> y; // Função Construtora int area () {return x * y; ; int main () { int i; cout << "Quantos objetos retangulo deseja criar?" << endl; cin >> i; Retangulo *Ret= new Retangulo[i]; for (int j = 0; j < i; j++) cout << "Area" << "[" << j << "] = " << Ret[j].area() << endl; delete[] Ret; return 0;
Arrays de objetos (inicialização individual) #include <iostream> using namespace std; 31 Retangulo (){x =0 ; y = 0; // Função Construtora void set(int a, int b){x =a; y = b; int area () {return x * y; ; int main () { int i; cout << "Quantos objetos retangulo deseja criar?" << endl; cin >> i; Retangulo *Ret= new Retangulo[i]; for (int j = 0; j < i; j++){ int a, b; cout << "x" << "[" << j << "] = " << endl; cin >> a; cout << "y" << "[" << j << "] = " << endl; cin >> b; Ret[j].set(a,b); for (int j = 0; j < i; j++) cout << "Area" << "[" << j << "] = " << Ret[j].area() << endl; delete[] Ret; return 0;
Arrays de objetos (acesso via ponteiro) #include <iostream> using namespace std; 32 Retangulo (){cin >> x; cin >> y; // Função Construtora int area () {return x * y; ; int main () { int i; cout << "Quantos objetos retangulo deseja criar?" << endl; cin >> i; Retangulo *Ret= new Retangulo[i]; for (int j = 0; j < i; j++) cout << "Area" << "[" << j << "] = " << (Ret + j)->area() << endl; delete[] Ret; return 0;
Sumário *x apontado por x &x endereço de x x.y membro y do objeto x x->y membro y do objeto apontado por x (*x).y membro y do objeto apontado por x (equivalente ao anterior) x[0] primeiro objeto apontado por x x[1] segundo objeto apontado por x x[n] (n+1)ésimo objeto apontado por x 33
Membros estáticos Um classe pode ter membros estáticos Um membro estático contem o mesmo valor para todos os objetos da classe Sintaxe: static int n; static float A; 34
Exemplo: contagem do número de objetos criados e destruídos #include <iostream> using namespace std; static int n; // n é uma variável estática Retangulo (){n++; // Função Construtora ~Retangulo (){n--; // Função Destrutora int area () {return x * y; ; 35 int Retangulo::n=0; // Inicialização da variável estática n (DEVE SER DECLARADA COMO GLOBAL) int main () { Retangulo *Ret= new Retangulo[5]; cout << "n = " << Retangulo::n << endl ; Retangulo *A= new Retangulo; cout << "n = " << Retangulo::n << endl ; delete[] Ret; delete A; Retangulo *B= new Retangulo[3]; cout << "n = " << Retangulo::n << endl ; delete[] B; Retangulo C, D; cout << "n = " << Retangulo::n << endl ; return 0;
Exercícios Faça um programa baseado na declaração de um classe aluno, que tenha como variáveis membros: nome, idade, matrícula, endereço, CEP e CRE, e que, sendo estas variáveis privadas, só aceitem dados com verificação de conteúdo (exemplo, CRE deve estar entre 0 e 10; idade sempre positiva, etc.). Após isso, faça o cadastro de alguns alunos da turma e mostre na tela o cadastro. 36
Sobrecarga de operador Suponha a seguinte classe: 37 Retangulo (){x =0 ; y = 0; // Função Construtora void set(int a, int b){x =a; y = b; int area () {return x * y; ; E considere os seguintes objetos: Retangulo A, B, C; O que aconteceria se a seguinte operação for realizada: C = A + B; Erro de compilação!!!
#include <iostream> using namespace std; Retangulo (){x =0 ; y = 0; // Função Construtora ; Retangulo operator + (Retangulo); // Função sobrecarregada do operador binário "+" void set(int a, int b){x =a; y = b; void mostra(){cout << "(x= " << x << ", y= " << y << ")" << endl;; int area () {return x * y; Retangulo Retangulo::operator + (Retangulo Temp){ Retangulo Temp2; Temp2.x = x + Temp.x; Temp2.y = y + Temp.y; return Temp2; int main () { Retangulo A, B, C; A.set(1,2); B.set(3,4); C = A + B; C.mostra(); Sobrecarga de operador Binário 38 return 0;
#include <iostream> using namespace std; Retangulo (){x =0 ; y = 0; // Função Construtora Retangulo operator + (Retangulo); // Função sobrecarregada do operador binário "+" void operator ++ () // Função sobrecarregada do operador unário "++" { x++; y++; void set(int a, int b){x =a; y = b; void mostra(){cout << "(x= " << x << ", y= " << y << ")" << endl;; int area () {return x * y; ; Retangulo Retangulo::operator + (Retangulo Temp){ Retangulo Temp2; Temp2.x = x + Temp.x; Temp2.y = y + Temp.y; return Temp2; int main () { Retangulo A, B, C; A.set(1,2); B.set(3,4); C = A + B; C.mostra(); A++; // Operador unário sobrecarregado A.mostra(); return 0; Sobrecarga de operador Unário 39
Sobrecarga de operador Observações gerais: Em geral, é adequado respeitar a definição original do operador Exemplo: sobrecarregar o operador + deve ser algo relacionado com adição Não é possível mudar o operador de unário para binário. Não se pode inventar novos operadores. Não é possível modificar a precedência de operadores por meio de sobrecarga. Operadores que não podem ser sobrecarregados:. (operador ponto) :: (operador de resolução de escopo)? : (operador ternário) 40
Operador ternário? O operador? avalia uma expressão condicional e retorna um valor se a expressão for true e um outro valor de for false Sintaxe (condição)? valor1 : valor2 Exemplo com if if (x == 20) // Se x for igual a 20 else y = 50; // então faço y receber 50 y = 70; // senão faço y receber 70 Exemplo com? int y = (x == 20)? 50 : 70; // y recebe 50 se x for igual a 20, senão recebe 70. 41
Exercício Faça a sobrecarga dos operadores abaixo: - (subtração) -- (decremento) 42
A palavra-chave this Representa um ponteiro para o objeto corrente cuja função está sendo executada. This também é conhecido como operador de AUTOREFERÊNCIA 43
#include <iostream> using namespace std; 44 Retangulo (){x =0 ; y = 0; // Função Construtora Retangulo operator + (Retangulo); // Função sobrecarregada do operador binário "+" void operator ++ () // Função sobrecarregada do operador unário "++" { x++; y++; void set(int a, int b){x =a; y = b; void mostra(){cout << "(x= " << x << ", y= " << y << ")" << endl;; int area () {return x * y; ; Retangulo Retangulo::operator + (Retangulo Temp){ this->x = x + Temp.x; this->y = y + Temp.y; return *this; int main () { Retangulo A, B, C; A.set(1,2); B.set(3,4); C = A + B; C.mostra(); A++; // Operador unário sobrecarregado A.mostra(); return 0;
Estruturas (struct) Por definição uma struct é uma classe na qual os membros são públicos por default Lembre-se que em uma classe os membros são privados por default 45 struct Retangulo {......
struct 46 x e y são privados int area () {return x * y; ; Existe diferença? struct Retangulo { x e y são públicos int area () {return x * y; ;
struct 47 x e y são privados int area () {return x * y; ; Existe diferença? struct Retangulo { private: x e y são privados int area () {return x * y; ;
Exercício Crie uma estrutura de dados para o objeto quadrado e que tenha uma função membro que compute sua área. Obs: use struct em vez de class 48