A apresentação está carregando. Por favor, espere

A apresentação está carregando. Por favor, espere

2002 LCG/UFRJ. All rights reserved. 1 Tópicos em C++ Claudio Esperança Paulo Roma Cavalcanti.

Apresentações semelhantes


Apresentação em tema: "2002 LCG/UFRJ. All rights reserved. 1 Tópicos em C++ Claudio Esperança Paulo Roma Cavalcanti."— Transcrição da apresentação:

1 2002 LCG/UFRJ. All rights reserved. 1 Tópicos em C++ Claudio Esperança Paulo Roma Cavalcanti

2 2002 LCG/UFRJ. All rights reserved. 2 Classes e Objetos C++ é mais do que C com uns poucos sinos e apitos adicionais. O mecanismo básico para atingir programação orientada a objeto em C++ é o conceito de classe. Fornece formas de encapsulamento e proteção de informação. Permite reutilização de código.

3 2002 LCG/UFRJ. All rights reserved. 3 O que é OO? Programação orientada a objeto foi o paradigma dominante dos anos 90. Criou o conceito de objeto, que é um tipo de dado com uma estrutura e um estado. Cada objeto define um conjunto de operações que podem acessar ou manipular esse estado. Tipos definidos pelo usuário devem se comportar da mesma maneira de tipos pré- definidos (fornecidos pelo compilador).

4 2002 LCG/UFRJ. All rights reserved. 4 Tipos de Dados Um tipo básico de dados de uma linguagem, como inteiro, real, ou caractere, fornece certas coisas: Podem-se declarar novos objetos, com ou sem iniciação. Pode-se copiar ou testar quanto à igualdade. Pode-se executar a entrada e a saída de dados com esses objetos.

5 2002 LCG/UFRJ. All rights reserved. 5 Objetos Um objeto é uma unidade atômica. Não pode ser dissecado por um programador. Proteção de informação torna os detalhes de implementação inacessíveis. Encapsulamento é o agrupamento de dados, e operações que se aplicam a eles, para formar um agregado. Mas escondendo a os detalhes de implementação. Uma classe é o mesmo que uma estrutura, mas com os membros protegidos por default.

6 2002 LCG/UFRJ. All rights reserved. 6 Encapsulamento O princípio de atomicidade é conhecido por encapsulamento. O usuário não tem acesso direto às partes de um objeto ou a sua implementação. O acesso é feito indiretamente, através de funções fornecidas com o objeto. É uma forma de imitar a vida real. Aparelhos eletrônicos possuem o seguinte aviso: Não abra – não há partes consertáveis por um usuário. Pessoas sem treinamento que tentam consertar equipamentos com esses avisos acabam quebrando mais do que consertando.

7 2002 LCG/UFRJ. All rights reserved. 7 Reutilização de Código A idéia é usar os mesmos componentes sempre que possível. Quando o mesmo objeto é a solução fica fácil. O difícil é quando se necessita de um objeto ligeiramente diferente. C++ fornece diversos mecanismos para isso. Se a implementação for idêntica exceto pelo tipo básico do objeto, pode-se usar uma template. Herança é o mecanismo que permite estender a funcionalidade de um objeto.

8 2002 LCG/UFRJ. All rights reserved. 8 Classes Classes são usadas para encapsular informação. Já que as funções que manipulam o estado do objeto são membros da classe, elas são acessadas pelo operador., como em uma estrutura de C. Quando se chama uma função de uma classe, na realidade se está passando uma mensagem para o objeto. A diferença básica entre OO de C++ e o velho C é puramente filosófica: em C++ o objeto tem o papel principal.

9 2002 LCG/UFRJ. All rights reserved. 9 Para Não Esquecer Jamais Se você deseja usar OO, acostume-se a esconder todos os dados das classes. C++ não é uma linguagem para preguiçosos. Para isto existe uma seção de dados privados. O compilador se esforçará ao máximo para mantê-los inacessíveis ao mundo exterior. Toda classe possui um construtor e um destrutor, que dizem como uma instância do objeto deve ser iniciada e destruída. Procure escrevê-los sempre. Evite defaults.

10 2002 LCG/UFRJ. All rights reserved. 10 class memoryCell { public: memoryCell ( ) { value = 0; } int read ( ) const { return value; } void write ( int x ) { value = x; } private: int value; }; Exemplo Bobo Construtor value está protegido

11 2002 LCG/UFRJ. All rights reserved. 11 Uso da Classe main ( ) { memoryCell m; m.write ( 5 ); cout << Conteúdo da célula é: #if 1 << m.read ( ) #else << m.value #endif << \n; return 0; } Instancia a classe Armazena um valor Maneira correta Erro!!! value é privado!!! Diretiva de pré- processamento

12 2002 LCG/UFRJ. All rights reserved. 12 Interface A interface descreve o que pode ser feito com o objeto. Necessita de uma boa convenção de nomes. Exemplo: primeira letra de nome de classe ou função minúscula, demais palavras do nome com primeira letra maiúscula (sem _). memoryCell. Dados: ponteiros com prefixo ptr e pode usar _. Constantes e tipos enumeráveis em caixa alta: GL_FLOAT, GLUT_DOUBLE; Prefixo com o nome do pacote. glLoadIdentity(), glVertex3f.

13 2002 LCG/UFRJ. All rights reserved. 13 Documentação É fundamental uma documentação mínima em todo o arquivo de um sistema. Existem ferramentas muito boas de domínio público, como o Doxygen. Basta colocar diretivas na forma de comentários na própria interface. É melhor acrescentar as diretivas durante a confecção da interface para não ter de voltar depois de má vontade.

14 2002 LCG/UFRJ. All rights reserved. 14 Interface memoryCell // memoryCell.h // evita incluir a interface de novo se ela já foi // incluída por outro arquivo. #ifndef __MEMORY_CELL__ #define __MEMORY_CELL__ /** * A very simple interface for a generic class. * Doxygen will generate the documentation, * in html, rtf and/or latex automatically. */ class memoryCell { public: /** empty construtor. * Sets the content of this cell to value. * value new value for this cell. */ memoryCell ( int value = 0 ); /// destrutor. Não faz nada. ~memoryCell ( ) { }

15 2002 LCG/UFRJ. All rights reserved. 15 Interface memoryCell /** the correct way of returning the content of this cell. the content of this cell. */ int read ( ) const; /** sets a new value for this cell. x new value. */ void write ( int x ); private: /// holds the content of this cell. int cell_value; }; #endif Não altera dados desta classe Altera dados desta classe

16 2002 LCG/UFRJ. All rights reserved. 16 Implementação A implementação contém os detalhes de como a interface foi codificada, de forma a atender as especificações do projeto. As declarações dos nomes das funções ficam na declaração da classe e as implementações são definidas depois, normalmente num arquivo separado (.C,.cpp, ou.cc). Usam a sintaxe de função mais o nome da classe e o operador de escopo ::.

17 2002 LCG/UFRJ. All rights reserved. 17 Implementação memoryCell // memoryCell.C #include memoryCell.h memoryCell::memoryCell ( int value ) { this->cell_value = value; } int memoryCell::read ( ) const { return this->cell_value; } void memoryCell::write ( int x ) { this->cell_value = x; } ConstrutorgettersetterMembro desta classe

18 2002 LCG/UFRJ. All rights reserved. 18 Construtores e Destrutores O construtor diz como o objeto é declarado e iniciado. Se a iniciação não casar com nenhum construtor, o compilador reclamará. O destrutor diz como o objeto será destruído quando sair de escopo. No mínimo deve liberar a memória que foi alocada por chamadas newno construtor. Se nenhum destrutor for declarado será gerado um default, que aplicará o destrutor correspondente a cada dado da classe.

19 2002 LCG/UFRJ. All rights reserved. 19 Construtor de Cópia O construtor de cópia é chamado sempre que o objeto for passado ou retornado por valor. Se nenhum for declarado será criado um default, que aplicará o construtor de cópia correspondente a cada dado da classe. Se a declaração for privada, o construtor de cópia será desativado (não poderá ser invocado). Ou escreva um construtor de cópia decente ou então desative-o.

20 2002 LCG/UFRJ. All rights reserved. 20 memoryCell ( const memoryCell& m ) { *this = m; } Uso: memoryCell m1 ( 4 ); memoryCell m2 ( m1 ); Exemplo de Construtor de Cópia Operador de atribuição Construtor de Cópia

21 2002 LCG/UFRJ. All rights reserved. 21 Operador de Atribuição É usado para copiar objetos do mesmo tipo. O operador de cópia cria um novo objeto, mas o operador = age sobre um objeto já existente. Operadores de atribuição retornam, em geral, referências constantes. Retorno por valor não é uma boa idéia... Retornar uma referência não constante torna (A = B) = C válido, mas sem sentido. O resultado é atribuir C à referência A, sem nunca ter atribuído à B. Se não for definido haverá uma cópia membro a membro dos dados da classe por default.

22 2002 LCG/UFRJ. All rights reserved. 22 Exemplo de Operador = const memoryCell& memoryCell::operator = ( const memoryCell& m ) { this->cell_value = m.cell_value; return *this; } Uso: memoryCell m1 ( 4 ); memoryCell m2 = m1; Referência para este objeto Operador de atribuição

23 2002 LCG/UFRJ. All rights reserved. 23 Iniciação X Construtor memoryCell ( int value = 0 ) : cell_value ( value ) { } A seqüência depois de : é a lista de iniciação. Os membros são iniciados na ordem em que são declarados e não na ordem da lista. O ideal é iniciar cada membro da classe pelo seu próprio construtor. É preferível iniciar os membros da classe usando listas de iniciação ao invés de atribuir no construtor. Cada membro não especificado na lista é iniciado pelo seu construtor vazio. Só depois é que as atribuições são feitas (trabalho dobrado). Se a iniciação não for simples, só aí usa-se o corpo do construtor.

24 2002 LCG/UFRJ. All rights reserved. 24 Sobreposição de Operadores Em C++ todos os operadores podem ser sobrepostos, a exceção de:.,.*, ? esizeof. Precedência e aridade não são alteradas. Um operador binário retorna, em geral, um objeto por valor, porque o resultado é armazenado em um temporário. Também pode ser implementado invocando o operador de atribuição.

25 2002 LCG/UFRJ. All rights reserved. 25 Exemplo de Sobreposição const memoryCell& memoryCell::operator += ( const memoryCell& m ) { this->cell_value += m.cell_value; return *this; } memoryCell memoryCell::operator + ( const memoryCell& m ) const { memoryCell temp ( *this ); temp += m; return temp; } Referência para este objeto Adiciona o segundo operando Retorna temp por valor

26 2002 LCG/UFRJ. All rights reserved. 26 Templates Templates servem para escrever rotinas que funcionam para tipos arbitrários. O mecanismo baseado em typedef permite criar rotinas genéricas. Mas não é suficiente se queremos rotinas que funcionem com dois tipos diferentes. Uma template não é uma função comum, mas sim um padrão para criar funções. Quando uma template é instanciada com um tipo particular, uma nova função é criada. A template é expandida (como uma macro) para prover uma função real. O compilador gera código a partir da template para cada combinação diferente de parâmetros.

27 2002 LCG/UFRJ. All rights reserved. 27 Exemplo de Função Template template inline const Etype& Max ( const Etype& a, const Etype& b ) { return a > b ? a : b; } Etype define o tipo do parâmetro da template. O código da template pode ser substituído como uma macro, caso se use a opção inline. Deve-se retornar uma referência, pois não se sabe de antemão o tamanho do dado retornado. O operador >deve estar definido no tipo Etype.

28 2002 LCG/UFRJ. All rights reserved. 28 Classes Template A sintaxe é similar ao de uma função template. Não há sentido em gerar uma biblioteca de templates. Lembre-se que o compilador não sabe que tipos serão necessários. Logo, não gera código algum. Ou todo o código da template está junto com a interface, ou a template deve ser instanciada de antemão para cada tipo a ser usado na aplicação.

29 2002 LCG/UFRJ. All rights reserved. 29 Template memoryCell // memoryCell.h #ifndef __MEMORY_CELL__ #define __MEMORY_CELL__ /** * A very simple interface for a template class. */ template class memoryCell { public: /** empty construtor. * Sets the content of this cell to value. */ memoryCell ( const Etype& value = Etype() ) { cell_value = value; } /** the correct way of returning the content of this cell. the content of this cell. */ const Etype& read ( ) const { return cell_value; } /** sets a new value for this cell. x new value. */ void write ( const Etype& x ) { cell_value = x; } private: /// holds the content of this cell. Etype cell_value; }; #endif Especificação template antes da classe Referência constante Pode assumir qualquer tipo

30 2002 LCG/UFRJ. All rights reserved. 30 Uso da Template memoryCell main ( ) { memoryCell m; m.write ( 5 ); cout << Conteúdo da célula é: #if 1 << m.read ( ) #else << m.cell_value #endif << \n; return 0; } Instancia a template com int

31 2002 LCG/UFRJ. All rights reserved. 31 Herança Talvez o principal objetivo de programação orientada a objeto seja a reutilização de código. Templates são apropriadas quando a funcionalidade básica do código é independente de tipo. Herança serve para estender a funcionalidade de um objeto. Criam-se novos tipos com propriedades restritas ou estendidas do tipo original.

32 2002 LCG/UFRJ. All rights reserved. 32 Polimorfismo Polimorfismo permite que um objeto possa armazenar vários tipos diferentes de objetos. Quando uma operação for aplicada a um objeto polimorfo será selecionada automaticamente aquela adequada ao tipo armazenado. Sobreposição (overload) de funções e operadores é um exemplo de polimorfismo. Neste caso, a seleção da função é feita em tempo de compilação, o que limita o comportamento polimorfo.

33 2002 LCG/UFRJ. All rights reserved. 33 Reutilização Em C++ é possível postergar a seleção da função até que o programa esteja sendo executado. O mecanismo básico usa herança. Freqüentemente, no projeto de uma nova classe, descobre-se que há uma classe similar escrita anteriormente. Reutilização de código sugere que não se comece do zero, mas que se escreva uma nova classe baseada na classe existente. Em C++ o mecanismo é criar uma classe abstrata polimorfa que possa armazenar os objetos das classes similares.

34 2002 LCG/UFRJ. All rights reserved. 34 Exemplos Classe Vetor: Vetores limitados. Classe Data: Calendários diversos (Gregoriano, Hebreu, Chinês). Impostos: vários tipos de contribuintes (solteiro, casado, separado, cabeça de casal). Formas: (círculos, quadrados, triângulos).

35 2002 LCG/UFRJ. All rights reserved. 35 Três Opções Definir classes completamente independentes. Implica em escrever vários pedaços de código idênticos. Aumenta a chance de erro e cada mudança deve ser replicada. Usar uma única classe e controlar as funções por if / else e switches. Manutenção é difícil, pois cada alteração requer recompilar todo o código. Extensão das classes por um programador não é possível a menos que todo o fonte esteja disponível. If / else gasta tempo de execução, mesmo que o resultado seja conhecido em tempo de compilação. Não há segurança de tipos, pois se toda forma está contida em uma única classe, pode-se atribuir um círculo a um triângulo.

36 2002 LCG/UFRJ. All rights reserved. 36 Derivação Derivar classes a partir de uma classe base (herança). Uma classe derivada herda todas as propriedades da classe base. Cada classe derivada é uma nova classe. Logo, a classe base não é afetada por mudanças nas classes derivadas. Uma classe derivada é compatível por tipo com a base, mas o contrário é falso. Classes irmãs não são compatíveis por tipo.

37 2002 LCG/UFRJ. All rights reserved. 37 Análise As primeiras duas opções são típicas de programação procedural. A terceira opção é aquela que deve ser adotada em programação orientada a objeto. class Derivada: public Base { // membros não listados são herdados. public: // construtores e destrutores (em geral // diferentes da base) // membros da base sobrepostos // novos membros públicos private: // dados adicionais (geralmente privados) // funções privadas adicionais // membros da base a serem desativados };

38 2002 LCG/UFRJ. All rights reserved. 38 Uso de Ponteiros com Herança Ponteiro para classe base classeBase* bPtr = NULL; classeBase bVar; Objeto do tipo base. bPtr = &bVar; Trivialmente válido. bPtr = &dVar; dVar é do tipo classeDerivada. bPtr->print(); Chama print da classe base. Ponteiro para classe derivada classeDerivada* dPtr = NULL; classeDerivada dVar; Objeto do tipo derivado. dPtr = &dVar; Trivialmente válido. dPtr = &bVar; ERRO!! dPtr->print(); Chama print da derivada.

39 2002 LCG/UFRJ. All rights reserved. 39 Apontar Ponteiro Derivado para Classe Base Gera erro. Classe derivada pode ter métodos e variáveis que não existem na classe base. Objeto da classe base não é do mesmo tipo do objeto da classe derivada.

40 2002 LCG/UFRJ. All rights reserved. 40 Apontar ponteiro Base para Classe Derivada Mecanismo válido. Mas só podem ser chamados métodos da classe base. Chamada a métodos da classe derivada gera erro. Tipo de um ponteiro ou referência define os métodos que podem ser invocados.

41 2002 LCG/UFRJ. All rights reserved. 41 Funções Virtuais Objetos (e não os ponteiros) definem os métodos que devem ser invocados. Suponha círculo, triângulo e retângulo derivados de uma classe forma. Cada um com seu próprio método de desenho (draw). Para desenhar qualquer forma, chama-se draw a partir de um ponteiro para forma. O programa determina, em tempo de execução, qual draw chamar (formas são tratadas de maneira genérica).

42 2002 LCG/UFRJ. All rights reserved. 42 Declaração Virtual Draw deve ser declarada virtual na classe base. Sobreponha-se draw em cada classe derivada. As assinaturas devem ser idênticas. Um vez declarada virtual, será virtual em todas as classes derivadas. É boa prática manter a declaração virtual nas classes derivadas, embora não seja mandatário.

43 2002 LCG/UFRJ. All rights reserved. 43 Tipos de Herança Pública: todos os membros públicos da classe básica permanecem públicos. Membros privados permanecem privados. Relacionamento É-Um (IS-A). Privada: mesmo membros públicos são escondidos. Relacionamento Tem-Um (HAS-A). É preferível usar composição do que herança privada. É a herança default.

44 2002 LCG/UFRJ. All rights reserved. 44 Herança de Construtores O estado de público ou privado dos construtores, construtor de cópia, e operador de atribuição são herdados. Se eles forem herdados, mas não definidos na classe derivada, os operadores correspondentes são aplicados a cada membro.

45 2002 LCG/UFRJ. All rights reserved. 45 Binding Estático e Dinâmico No binding estático a decisão de que função invocar para resolver uma sobreposição é tomada em tempo de compilação. No binding dinâmico a decisão é tomada em tempo de execução. C++ usa binding estático por default, porque se achava no passado que o overhead seria significativo. Para forçar o binding dinâmico o programador deve especificar a função como virtual.

46 2002 LCG/UFRJ. All rights reserved. 46 Porque binding dinâmico? Quando se declara um ponteiro para uma classe como argumento de uma função, normalmente o tipo do ponteiro é o da classe base. Assim, pode ser passada qualquer uma das classes derivadas e o tipo do objeto apontado é determinado em tempo de execução. Virtualidade é herdada. Funções redefinidas em classes derivadas devem ser declaradas virtuais. Uma decisão em tempo de execução só é necessária quando o objeto for acessado através de ponteiros.

47 2002 LCG/UFRJ. All rights reserved. 47 Construtores e Destrutores Virtuais? Construtores nunca são virtuais. Destrutores devem ser virtuais na classe base apenas. O tipo de um construtor sempre pode ser determinado em tempo de compilação. O destrutor deve ser virtual para garantir que o destrutor do objeto real é chamado. A classe derivada pode ter membros adicionais que foram alocados dinamicamente, que só podem ser desalocados pelo destrutor da classe derivada.

48 2002 LCG/UFRJ. All rights reserved. 48 Custo Polimorfismo tem um custo que impacta na performance. STL não usa polimorfismo por questão de eficiência. Cada classe com função virtual tem uma tabela vtable. Para cada função virtual, vtable tem um ponteiro para função apropriada. Se a classe derivada tiver a mesma função virtual da classe base, o ponteiro da vtable aponta para a função na base.

49 2002 LCG/UFRJ. All rights reserved. 49 Casting (compatibilização) Downcasting Operador dynamic_cast Determina o tipo do objeto em tempo de execução. Retorna 0 se não for o tipo certo (não pode sofrer cast) NewClass *ptr = dynamic_cast objectPtr; Pode compatibilizar endereço de objeto do tipo base para ponteiro para classe derivada.

50 2002 LCG/UFRJ. All rights reserved. 50 Informação de Tipo Keyword typeid Header Uso: typeid(object) Retorna type_info do objeto Tem informação sobre o tipo do operando, incluindo nome. typeid(object).name()

51 2002 LCG/UFRJ. All rights reserved. 51 Tipos de Classe Classes abstratas Único propósito: ser uma classe base (chamada classe base abstrata). Incompleta: possui métodos sem código. Classes derivadas preenchem pedaços omitidos. Objetos não podem ser instanciados a partir de classes abstratas. No entanto, pode haver ponteiros e referências. Classes concretas Podem instanciar objetos. Implementam todas as funções que definem. Provêem detalhes.

52 2002 LCG/UFRJ. All rights reserved. 52 Função Virtual Pura e Regular Classes abstratas não são necessárias, mas são úteis. Ponteiros para classes base abstratas são úteis no polimorfismo. Para criar uma classe abstrata: Precisa-se de uma ou mais função virtual "pura" Declare-se função com inicializador 0 virtual void draw() const = 0; Função virtual regular Possui implementações, e sobreposição é opcional. Função virtual pura Nenhuma implementação, mas deve ser sobreposta. Classes abstratas podem ter dados e funções concretas. Devem ter uma ou mais funções virtuais pura.

53 2002 LCG/UFRJ. All rights reserved. 53 Herdando Interface e Implementação 0.0 = "Point"[x,y] r 2 0.0"Circle" center=[x,y]; radius=r 2 r 2 +2 rh r 2 h "Cylinder" center=[x,y]; radius=r; height=h getAreaprintgetNamegetVolume Shape Point Circle Cylinder

54 2002 LCG/UFRJ. All rights reserved. 54 Funções de Desenho Exemplo clássico em OO: método draw. Colocar funções de desenho nas classes, requer acesso a um pacote gráfico nas classes (OpenGL,PHIGS,GKS,Direct X...). Será que é a forma adequada do ponto de vista de portabilidade? Alternativa melhor pode ser passar os objetos para uma classe de desenho. Apenas a pessoa que escreve essa classe precisa conhecer Computação Gráfica.


Carregar ppt "2002 LCG/UFRJ. All rights reserved. 1 Tópicos em C++ Claudio Esperança Paulo Roma Cavalcanti."

Apresentações semelhantes


Anúncios Google