PROGRAMAO ORIENTADA A OBJETOS EM C PAE Pedro
PROGRAMAÇÃO ORIENTADA A OBJETOS EM C++ PAE: Pedro Shiguihara Professor: Dilvan Moreira
Sobre C++
Principais diferenças entre Java e C++ O Java não trabalha de forma explícita com ponteiros O Java tem gerenciamento de memória através do Coletor de Lixo O Java não permite sobrecarga de operadores
Entrada/Saída Os operadores >> e << foram sobrecarregados para executar operações de entrada e saída. Todo programa, ao ser executado, recebe 4 referências para dispositivos externos cin (entrada padrão) cout (saída padrão) cerr (saída de erros)
Entrada/Saída Entrada/saída análogas a: System. in System. out System. err Exemplos: cin>>x; cout<<“Nome: ”<<n; cerr<<“Erro nr. ”<<nerro<<“n”;
Entrada/Saída //Programa que mostra a soma de dois números #include<iostream> int main(){ int number 1; std: : cout << "Digite o primeiro inteiro: "; std: : cin >> number 1; int number 2; int sum; std: : cout<<"Digite o segundo inteiro: "; std: : cin >> number 2; sum = number 1 + number 2; std: : cout << "A soma é "<< sum << std: : endl; }
Entrada/Saída Ativação de identificadores “cout”, “cin” e “endl” //Programa que mostra a soma de dois números #include<iostream> using std: : cout; using std: : cin; using std: : endl; int main(){ int number 1; cout << "Digite o primeiro inteiro: "; cin >> number 1; int number 2; int sum; cout<<"Digite o segundo inteiro: "; cin >> number 2; sum = number 1 + number 2; cout << "A soma é "<< sum << endl; }
Ponteiros Operador & Obtem o endereço da variável Operador * Obtem o valor armazenado no enderço de memória apontado pela variável
Ponteiros
Ponteiros #include<iostream> using namespace std; int main(){ int x = 3; int &y = x; cout << "X = " << x << endl << "y = " << y << endl; y = 7; cout << "x = " << x << endl << "y = " << y << endl; }
Operador de seleção de membro ponto (. ) É precedido pelo nome de um objeto ou por uma referência a um objeto para acessar os membros do objeto Operador de seleção de membro seta (->) É precedido por um ponteiro de um objeto para acessar os membros daquele objeto
Operador de seleção #include<iostream> using namespace std; //Definição da classe Count class Count { public: void set. X( int value ){ x = value; } void print(){ cout << x << endl; } private: int x; };
Operador de seleção int main(){ Count counter; Count *counter. Ptr = &counter; cout << "Define x como 1 e imprime usando o nome do objeto: "; counter. set. X( 1 ); counter. print(); cout << "Define x como 3 e imprime usando uma referência a um objeto: "; counter. Ptr->set. X ( 3 ); counter. Ptr->print(); }
Escopo de uma variável Uso de espaço de nomes (“using namespace std”) permite usar todos os nomes em qualquer arquivo de cabeçalho C++ que um programa poderia incluir Os símbolos “: : ” permitem definir o escopo de uma variável “: : ” é chamado operador unário de resolução de escopo
Escopo de uma variável //Programa que mostra a soma de dois números #include<iostream> using namespace std; int number = 7; int main(){ double number = 10. 5; //mostra valores de variáveis locais e globais cout << "Valor local double de number = " << number << "n. Valor global int de number = " << : : number << endl; }
Escopo de uma variável int x; class X{ int x; int f(); }; //retorna this->x int X : : f() {return x; } //retorna x cujo escopo é global int X : : f() {return : : x; } //retorna this-> x int X : : f() { int x = 3; return X: : x; } //retorna x cujo escopo é global int X : : f() { int x = 3; return : : x; }
Conceitos de Orientação a Objetos: Classes
Construtores São utilizados para instanciar e inicializar valores de objetos Em Java e C++ têm o mesmo nome da classe e nenhum tipo de retorno explícito Útil para definir características dos objetos ao serem instanciados
Construtores #include<iostream> using namespace std; //Definição da classe Count class Ponto { int x; int y; public: Ponto( int X, int Y ) { x = X; y = Y; } int Get. X() {return x; } int Get. Y() {return y; } };
Construtores int main(){ Ponto A(2, 5); Ponto *B = new Ponto(4, 5); cout << "Coord. X: " << A. Get. X() << endl; cout << "Coord. Y: " << A. Get. Y() << endl; cout << "Coord. X: " << B->Get. X() << endl; cout << "Coord. Y: " << B->Get. Y(); }
Destrutores Tudo que é alocado estaticamente fica na memória Stack (Pilha) Tudo que é alocado dinamicamente é colocado na memória Heap Quando um programa termina ele não libera a Heap • S. O. Pode liberar, mas não é garantido Portanto deve-se liberar usando um destrutor
Destrutores Em C++ é obrigatório o uso de destrutores Em Java há um coletor de lixo para isso! Não se usa destrutor Há uma chamada para o método finalize() de Object mas comumente não é utilizado
Criação de objetos de forma dinâmica Os operadores “new” e “delete”, além de alocar e liberar memória, chamam os construtores e destrutores do objeto O operador “delete” pode ser utilizado uma vez e somente em objetos que foram alocados pelo operador “new” Estes operadores podem ser utilizados em tipos embutidos de dados (int, char, . . . )
Criação de objetos de forma dinâmica
Outro conceito importante (this) A palavra reservada this é uma referência para o objeto da classe atual Essa referência pode ser utilizada em C++ ou Java Isso permite definir escopo de variáveis
Outro conceito importante (this) class Teste{ private: int x; int y; public: Teste(int , int ); }; Teste: : Teste(int x, int y){ this->x = x; this->y = y; }
Sobrecarga Sobrecarregar um método é tê-lo duas ou mais vezes definido dentro da mesma classe (ou subclasses) O que muda são os parâmetros enviados para o método Quantidade parâmetros Ordem em que os tipos foram definidos
Sobrecarga Permite declarar várias funções com o mesmo nome e que executem diferentes conjuntos de instruções, dependendo dos tipos de dados em que estão sendo aplicados Auxilia no tratamento de complexidades Permite que conjuntos relacionados de funções sejam acessados pelo mesmo nome Pode-se sobrecarregar: Funções Operadores (C++)
Sobrecarga de função //Funções sobrecarregadas #include<iostream> using namespace std; //função square para valores int square( int x ) { cout << "quadrado do int " << x << " é "; return x * x; } //função square para valores double square( double y ) { cout << "quadrado do double " << y << " é "; return y * y; } int main(){ cout << square( 7 ) << endl; cout << square( 7. 5 ) << endl; }
Sobrecarga de função membro Class X { public: void Solicitacao(char *Mensagem , int *i) { cout << Mensagem; cin >> *i; } void Solicitacao(char *Mensagem , float *f) { cout << Mensagem; cin >> *f; } void Solicitacao(char *Mensagem , long *l) { cout << Mensagem; cin >> *l; } };
Sobrecarga de função membro main() { X *x = new X(); int i; float f; long l; x->Solicitacao("n Informe um inteiro" , &i); x->Solicitacao("n Informe um float , &f); x->Solicitacao("n Informe um long" , &l); cout << 'n' << i << f << l; } Resultado: Informe um inteiro: 13 Informe um float: 1. 23 Informe um long: 1276 L 13 1. 23 1276 L
Sobrecarga de operadores Não podem ser sobrecarregados ->. ? : , Forma geral: Valor de retorno normalmente é do mesmo tipo da classe, para permitir atribuições múltiplas: a=b=c Funcionamento a=b+c A função operator+ do objeto b será chamada, passando c como parâmetro. O valor retornado por esta função será passado como parâmetro para a função operator= de a
Sobrecarga de operadores Para que um objeto de uma classe possa usar a atribuição é necessário que a classe sobrecarregue o operador “=“ A inicialização requer que a classe possua um construtor de cópia: class Minha { public: Minha( ); // construtor void Minha( Minha& ); // construtor de cópia }
Sobrecarga de operadores class Vetor { int * valor; int tamanho; public: //. . . void operator = (Vetor&); // sobrecarga do // operador de atribuição }; Vetor: : operator=( Vetor& vet ) { if (tamanho != vet. tamanho) error(“verifique tamanho”); for (int i = 0 ; i < tamanho ; i++) valor[i] = vet. valor[i]; } vet 1 = vet 2 // atribui vet 2 a vet 1, // isto é copia os elementos
Herança Pode-se construir uma nova classe baseada em uma anterior Isso permite reuso de código-fonte (comportamento de outras classes) Especializar classes Herdar características (identificadores) e comportamento (métodos)
Herança Uma classe pode ser derivada como: public, protected ou private
Herança Visibilidade dos membros da classe derivada:
Herança Múltipla
Herança Múltipla
Herança Múltipla class Empregado // classe base indireta para { // Vendedor. Gerente char Nome[50]; float Salario. Fixo; public: float Get. Salario( ); }; class Vendedor : public virtual Empregado { // Empregado é classe base // virtual para Vendedor float Comissao; }; class Gerente : public virtual Empregado { // Empregado é classe base // virtual para Empregado int Secao; }; class Vendedor. Gerente : public Vendedor, public Gerente { };
Métodos ou funções virtuais Um método (ou função) virtual é aquele que pode ser sobrescrito em uma classe filha Java permite sobrescrever todos métodos Todos são implicitamente virtuais C++ permite sobrescrever somente métodos definidos com a palavra especial virtual Deve-se especificar de maneira explícita
Métodos ou funções virtuais Função definida na classe base e que pode ser redefinida pelas classes derivadas, por outra função que tenha o mesmo nome e parâmetros Define-se uma função como virtual da seguinte forma: class Classe. Base { virtual int Funcao( ) // permite sobrescrever o método {//. . . } }; class Classe. Filha { Funcao( ) { // redefinição de Funcao } };
Métodos ou funções virtuais Uma função virtual pura é aquela cujo comportamento só será definido pelas classes derivadas Declaração: class G { virtual void Funcao( ) = 0; };
Métodos ou funções virtuais Uma classe que possua alguma função virtual pura é chamada de abstrata e não se pode declarar objetos desta classe.
Métodos ou funções virtuais class Pai // classe abstrata pois possui uma { // função virtual pura virtual void Funcao( ) = 0; // função virtual // pura //. . . }; class Filho : public Pai { void Funcao( ) // Filho define Funcao { // Pode-se ter objetos desta classe //. . . } }; class Outra : public Pai // Outra é uma classe { // abstrata pois não // define Funcao //. . . }
Métodos ou funções virtuais main( ) { Pai *Ponteiro. Pai; // OK, pode-se ter // ponteiros para // classes abstratas Outra O; // Erro, Outra é uma classe // abstrata e não se pode ter // objetos desta classe Filho F; // OK, Filho não é abstrata Ponteiro. Pai = new Filho; // OK, objeto da // classe Filho delete Ponteiro. Pai; Ponteiro. Pai = new Pai; // Erro, objeto de // classe abstrata }
Polimorfismo Pode-se classificar em dois tipos: Cast de objetos filhos em pais Chamadas de métodos (também conhecido como métodos virtuais ou polimorfismo de método)
Cast de Objetos filhos em Pais Considere uma herança entre a classe Pessoa (superclasse) e Funcionário (subclasse) Pode-se criar um objeto do tipo Funcionário e convertê-lo em uma Pessoa O contrário não é possível (mas C++ deixa!)
Cast de Objetos filhos em Pais
Leitura Caps. 15, 16 e 17 “Como programar em C”, 7 ma ed. , Deitel.
- Slides: 50