1/24 Classes Introdução
2/24 Tipos e operações Novos tipos de dados requerem operações associadas. Tipo: pilha Operações: inicializa, insere, retira, topo, vazia. Queremos essa relação indicada no código. struct + funções não fornece essa indicação. Tipo é caracterizado pelas operações, e não pela implementação. Ex: pilha.
Ocultamento de implementação O cliente não deve ter acesso à implementação. Se cliente usa detalhes de implementação: Fica difícil alterar implementação (código do cliente depende da implementação que ele usou). Cliente pode alterar detalhes inconsistentemente (fora do que é esperado pelo tipo de dados). Exemplo em pilha com struct. 3/24
4/24 Interface e implementação É necessário determinar claramente o que é parte da implementação e o que é interface: Implementação: detalhes que não interessam aos clientes. Interface: Determina o acesso pelo cliente. É necessário associar as operações com os tipos. Feito em orientação a objetos por meio de classes.
5/24 Classes Classes em C++
6/24 Classes Definem um tipo de dados. Especificam as operações sobre esse tipo. Determinam a implementação: Da representação do tipo. Das operações. A separação entre o que é interface e o que é implementação é chamada controle de acesso.
7/24 Controle de acesso A implementação da classe é definida por: Código da implementação das operações. Membros privados (não acessíveis aos clientes). Em uma classe, os membros são privados, a menos que seja indicado em contrário. Os membros públicos devem ser precididos pelo rótulo public. Membros públicos definem a interface.
Membros privados Nome do tipo Membros públicos Exemplo Representação do tipo class Rational { int _numerator, _denominator; public: void set(int num, int den); void set(const Rational &r); int numerator(); int denominator(); Rational plus(const Rational &b); Rational minus(const Rational &b); Rational times(const Rational &b); Rational over(const Rational &b); double to_double(); }; Operações sobre o tipo 8/24
9/24 Nomenclatura Classes têm dois tipos de membros: Membros tipo dados, também chamados campos. Membros tipo função, também chamados funções membro ou métodos. Normalmente os membros tipo dados são privados (fazem parte da implementação). Os membros públicos são métodos (operações sobre o tipo). Há exceções!
10/24 Nomenclatura Uma classe define um tipo de dados. Uma variável (ou elemento alocado dinamicamente) desse tipo é denominada um objeto da classe, ou uma instância da classe. Rational r; Objeto ou instância da classe Rational.
11/24 Acesso a membros O acesso a membros (tipo dados ou funções) é feito através de um objeto com o operador de acesso a membro. Envio da mensagem set ao objeto b. Rational a, b, c; b.set(1,2); c.set(2,3); a.set(b.times(c));
Exemplo Nome da classe Operador de escopo Nome do método void Rational::set(int num, int den) { _numerator = num; _denominator = den; } Membros privados da classe podem ser acessados por qualquer método da classe. void Rational::set(const Rational &r) { _numerator = r._numerator; _denominator = r._denominator; } Membros do objeto que recebeu a mensagem. Membros do objeto parâmetro. 12/24
13/24 Exemplo (cont) int Rational::numerator() { return _numerator; } int Rational::denominator() { return _denominator; }
14/24 Exemplo (cont) Rational Rational::times(const Rational &b) { Rational r; r.set(_numerator * b._numerator, _denominator * b._denominator); return r; } Rational Rational::over(const Rational &b) { Rational r; r.set(_numerator * b._denominator, _denominator * b._numerator); return r; }
15/24 Exemplo (cont) Rational Rational::plus(const Rational &b) { Rational r; int n, d; n = _numerator * b._denominator + _denominator * b._numerator; d = _denominator * b._denominator; r.set(n, d); return r; } Rational Rational::minus(const Rational &b) { // Similar }
16/24 Exemplo (cont) double Rational::to_double() { return static_cast<double>(_numerator) / _denominator; }
17/24 Compilação separada Geralmente se usa compilação separada. Definição da classe (com protótipos dos métodos) vai num arquivo cabeçalho. Definição dos métodos vai num arquivo de implementação. Código cliente (possivelmente vários) em arquivo separado.
18/24 Exemplo Rational: código e execução
19/24 Encapsulação A implementação fica encapsulada pela interface. Impossibilidade de acesso à implementação facilita realização de alterações. Alterações na implementação garantidamente não afetam clientes. Alterações na interface afetam clientes, e devem ser evitadas. Cuidado no desenvolvimento da interface.
20/24 Exemplo Exemplo Rational com simplificação. Ver também exemplo de classe Complexo (apostila, seção 7.1)
21/24 Ponteiros como membros Quando alguns membros são ponteiros é necessário tomar certos cuidados. Queremos impedir que cliente altere valor do objeto. Dados controlados pelo cliente devem ser copiados internamente na entrada. Ao retornar ao cliente: Fazer uma cópia, ou Garantir que não pode ser alterado (const).
22/24 Exemplo Exemplo de nomes. Ver também exemplo de classe Cadeia (apostila, seção 7.1)
23/24 Controle de acesso O controle de acesso é feito através dos rótulos: public: indica a parte acessível ao cliente (interface) private: indica a parte não acessível ao cliente (implementação). A diferença entre struct e class é apenas a acessibilidade default. Usamos class para tipos abstratos.
24/24 Equivalentes class A { int a; public: void f(int x); int g(); }; class A { public: void f(int x); int g(); private: int a; }; class A { private: int a; public: void f(int x); int g(); }; struct A { public: void f(int x); int g(); private: int a; }; class A { public: void f(int x); private: int a; public: int g(); }; struct A { void f(int x); int g(); private: int a; };