Linguagem de
Programação II
Carlos Oberdan Rolim
Ciência da Computação
Sistemas de Informação
Classes
Herança
Herança de classes
É um relacionamento existente entre classes que permite a
criação de outras novas classes a partir das classes
existentes
Reutilização de código
Poupa tempo de programação
Classes criadas a partir de outras herdam algumas ou todas
as caracteristicas (variaveis-membro e métodos)
Herança de classes
Classe-base: classe que dá origem a outras
Classes derivadas: aquelas que nascem a partir de uma
classe-base
Classes derivadas podem criar métodos ou atributos para
atender necessidades especificas
Estrutura de uma classe e suas classes derivadas é
chamada de hierarquia de classes
Heranças simples
Tipo mais simples de herança
class classe-deriv : tipo classe-base declaração
Onde:
class: palavra reservada
classe-deriv: nome da classe derivada
tipo: tipo de herança ou derivação. Diz respeito aonde os
membros da classe-base poderão ser utilizados. Pode ser
public, protected ou private
classe-base: nome da classe base
declaração: declaração da classe derivada
Heranças simples
Classe base
Classe derivada
Representação grafica
class carro {
public:
void exibe();
private:
char marca[12];
char modelo[10];
};
class novo-carro :public carro {
public:
exibe_novo();
private:
int anofab;
}
Tipos de herança
Public
Membros publicos da classe-base se tornam publicos na classe
derivada
Membros protegidos na classe-base se tornam protegidos na classe
derivada
Membros privados na classe-base se tornam privados na classe
derivada, podendo ser acessados apenas pelos metodos publicos e
protegidos (da seção protected) da classe-base
Construtores da classe-base não são herdados na classe derivada.
Se não chamar de forma explicita o construtor da classe-base este
será chamado por default para construir parte do novo ojeto
Destrutores não são herdados
Quando objeto é destruido executa destrutor da classe derivada e
depois destrutor da classe-base
Tipos de herança
Private
Membros púlicos e protegidos da classe-base torna-se privados na
classe derivada
Quer dizer que os metodos da classe base não se tornam publicos no
objeto derivado
Esses metodos podem ser usados dentro dos metodos da classe
derivada
É o tipo de herança default
Tipos de herança
Protected
Variação da herança privada
Membros publicos e protegidos da classe-base torna-se membros
protegidos da classe derivada, podendo ser acessados pela classe
derivada como se fossem publicos
Para o resto do programa os membros protegidos serão considerados
como privados, precisando ser acessados pelos métodos da classebase
class carro {
public:
carro(char *, char *);
char marca[12];
char modelo[10];
int main (){
novo_carro n1(“Ford”, “Focus”, 2002);
n1.exibe_tudo();
return 0;
}
};
class novo_carro :public carro {
public:
novo_carro( char*, char*, int);
void exibe_tudo();
private:
int anofab;
}
carro :: carro( char * m1, char *m2){
strcpy(marca, m1);
strcpy(modelo, m2);
}
novo_carro :: novo_carro(char *m1,
char * m2, int a) : carro(m1, m2){
anotab = a;
}
void novo_carro ::exibe_tudo(){
cout << “Marca” << marca << endl;
cout << “Modelo” << modelo << endl;
cout << “Ano: “ << anofab << endl;
}
Exemplo com variaveis-membro definidas como public
Informações adicionais
Membros públicos da classe-base tornam-se membros
públicos na classe derivada. Por isso método exibe_tudo
mostra variáveis-membro da classe-base
Protótipo contém referencia as duas variaveis-membro da
classe-base seguidas da referência criada na classe
derivada
Informações adicionais
Na definição do construtor
novo_carro :: novo_carro(char *m1, char * m2, int a) :
carro(m1, m2)
carro(m1, m2) é uma lista de inicialização de variáveismembro que chama o construtor da classe-base.
Um construtor da classe derivada precisa chamar o
construtor da classe-base.
Construtor da classe carro cria objeto do tipo carro e então
construtor da classe derivada completa criação dos objetos
Quando criado objeto da classe derivada cria-se primeiro o
objeto da classe-base
class carro {
public:
carro(char *, char *);
void exibe();
private:
char marca[12];
char modelo[10];
};
class novo_carro :public carro {
public:
novo_carro( char*, char*, int);
void exibe_novo();
private:
int anofab;
};
int main() {
carro carro1(“GM”, “Corsa”);
novo_carro n1(“Ford”, “Focus”, 2002);
carro1.exibe();
n1.exibe_novo();
n1.exibe(); // derivada chama base
return 0;
}
void carro ::exibe(){
cout << “Marca” << marca << endl;
cout << “Modelo” << modelo << endl;
}
carro :: carro( char * m1, char *m2){
strcpy(marca, m1);
strcpy(modelo, m2);
}
novo_carro :: novo_carro(char *m1,
char * m2, int a) : carro(m1, m2){
anotab = a;
}
void novo_carro ::exibe_novo(){
exibe(); // classe-base
cout << “Ano: “ << anofab << endl;
}
Exemplo com variaveis-membro definidas como private
Informações adicionais
Entre uma classe-base e sua classe derivada existe um
relacionamento que permite a um objeto da classe derivada
chamar um metodo da classe-base o que é mostrado na
linha n1.exibe()
class carro {
public:
carro(char *, char *);
protected:
char marca[12];
char modelo[10];
};
class novo_carro :public carro {
public:
novo_carro( char*, char*, int);
void exibe_tudo();
private:
int anofab;
};
void novo_carro ::exibe()_tudo{
cout << “Marca” << marca << endl;
cout << “Modelo” << modelo << endl;
cout << “Ano” << anofab << endl;
}
carro :: carro( char * m1, char *m2){
strcpy(marca, m1);
strcpy(modelo, m2);
}
novo_carro :: novo_carro(char *m1,
char * m2, int a) : carro(m1, m2){
anotab = a;
}
int main() {
novo_carro ncarro1(“Ford”, “Focus”, 2002);
ncarro1.exibe_tudo();
return 0;
}
Exemplo com variaveis-membro definidas como protected
Informações adicionais
A classe-base declara membros que são acessados pela
classe derivada
Como os membros protegidos da classe-base se tornam
privados na classe derivada o método exibe_tudo() exibe as
variáveis-membro da classe-base também
Com membros iguais nas classes base e derivada, utiliza-se
o operador de escopo :: para particularizar o acesso, no
formato classe-base::membro e classe-derivada::membro
Tipos de herança
Tipo de herança
Membros da
classe
Public
Private
Protected
Publicos
São publicos da São privados
classe derivada da classe
derivada
São protegidos
da classe
derivada
Privados
Acessiveis via
metodos da
classe base
Acessiveis via
metodos da
classe base
Acessiveis via
metodos da
classe base
Protegidos
São protegidos
na classe
derivada
São privados
da classe
derivada
São protegidos
da classe
derivada
Permissões de acesso
Tipo de herança
Classe derivada
Public
Private
Protected
Método acessa variável-membro pública da classe-base ?
Sim
Sim
Sim
Método acessa variável-membro privada da classe-base ?
Não
Não
Não
Método acessa variável-membro protegida da classe-base ?
Sim
Sim
Sim
Método chama método público da classe-base ?
Sim
Sim
Sim
Método chama método privado da classe-base ?
Não
Não
Não
Método chama método protegido da classe-base ?
Sim
Sim
Sim
Objeto acessa variável-membro pública da classe-base?
Sim
Não
Não
Objeto acessa variável-membro privada da classe-base?
Não
Não
Não
Objeto acessa variável-membro protegida da classe-base?
Não
Não
Não
Objeto chama método público da classe-base?
Sim
Não
Não
Objeto chama método público da classe-base?
Não
Não
Não
Objeto chama método público da classe-base?
Não
Não
Não
Classes-base abstratas
É o relacionamento onde uma classe-base serve somente de
modelo para outras classes derivadas
Pessoa
Sobrenome
CPF
Homem
Mulher
Idade
Peso
Estado civil
class pessoa {
public:
void le_dados();
void exibe();
private:
char snome[10];
char cpf[10];
};
class homem :public pessoa {
public:
void le_dados();
void exibe();
private:
int idade;
int peso;
};
class mulher :public pessoa {
public:
void le_dados();
void exibe();
private:
char est_civil[11];
};
int main() {
homem homem1;
mulher mulher1;
cout << “informe dados homem”;
homem1.le_dados();
cout << “informe dados mulher”;
mulher1.le_dados();
homem1.exibe();
mulher1.exibe();
}
void pessoa :: le_dados(){
cin >> snome;
cin >> cpf;
}
void homem :: le_dados(){
pessoa:: le_dados();
cin >> idade; cin >> peso;
}
Informações adicionais
Não foram criados objetos da classe pessoa. Essa classe é
utilizada como uma classe geral cujo objetivo único é de
atuar como uma base a partir da qual outras classes são
derivadas.
Classes cujo intuito é apenas derivar outras classes e sem a
criação de objetos são chamadas classes-base abstratas
ou simplesmente classes abstratas
Os membros privados da classe abstrata somente podem
ser acessados por ela mesmo (snome não pode ser
acessado pela classe homem por exemplo)
Mas no exemplo anterior o que impede a instanciação de
um objeto da classe pessoa ??
Métodos virtuais e classes abstratas
Esses slides serão vistos novamente quando for falado
sobre métodos virtuais...
Para impedir a criação de um objeto de uma classe-base
abstrata basta declarar um método como virtual puro na
classe-base
Para um método tornar-se virtual puro basta acrescer = 0 no
seu protótipo
Uma vez declarado um método virtual puro em uma classebase , este deverá ser redefinido nas classes derivadas em
que se deseja criar um objeto.
Se qualquer das classes derivadas não redefinir o método
virtual puro da classe-base, a classe derivada tornar-se-a
uma classe abstrata
class FormasGeo {
public:
virtual void desenhar() = 0;
};
Método virtual puro torna a classe
abstrata
class quadrado :public FormasGeo {
public:
void desenhar();
};
class retangulo :public FormasGeo {
public:
void desenhar_2();
};
Redefinição do método
Não redefiniu o método desenhar
int main ( ){
quadrado quadrado1;
// retangulo retangulo1;
}
Gera um erro pois classe retangulo
se tornou abstrata
class pessoa {
public:
virtual void le_dados() = 0;
virtual void exibe() = 0;
private:
char snome[10];
char cpf[10];
};
class homem :public pessoa {
public:
void le_dados();
void exibe();
private:
int idade;
int peso;
};
…… implementacao dos metodos ….
int main() {
homem homem1;
pessoa p ;
cout << “informe dados homem”;
homem1.le_dados();
homem1.exibe();
}
ERRO:
Cannot declare variable p to be type
of pessoa
because the following virtual functions
are abstract
Classe final
Existe momentos que não desejamos que uma classe possa
ser derivada
Essa classe é chamada de final
Em C++ para criar uma classe final declara-se o destrutor
como privado e cria-se um método estático retornando o
endereço da instância criada.
Implica no uso de ponteiros
C++ não é elegante como Java nesse ponto
Java possui a palavra reservada final para isso
class Pessoa {
int main(){
public:
static Pessoa * Criar(){
return (new Pessoa());
}
Pessoa *p;
p = Pessoa::Criar();
p->le_dados();
p->mostra_dados();
void le_dados();
void mostra_dados();
private:
~Pessoa(); // destrutor
string nome;
};
/* Se descomentado gera erro
class Homem :public Pessoa{
public:
Homem();
}
*/
.... Implementacao dos metodos ...
getch();
return 0;
}
Herança múltipla
É a herança na qual uma classe é derivada a partir de várias
classes-base
Classe-base 1
Classe-base 2
Classe derivada
Herança múltipla
Em termos de sintaxe
class P {
....
};
class Q {
....
};
class R : public P, public Q {
...
};
Ambigüidade em herança múltipla
Supondo a seguinte situação: duas classes-base contendo o
métodos com o mesmo nome e uma classe derivada de
ambas contendo métodos com nomes diferentes dos
métodos das classes-base. Assim surge a questão:
Como um objeto da classe derivada irá o método correto da
classe-base ?
Resposta: basta utiliza o operador de resolução de escopo ::
class base1 {
...
public:
void exibe();
};
class base2 {
...
public:
void exibe();
};
class derivada: public base1, public base2 {
...
};
int main () {
derivada obj;
obj.base1 :: exibe();
obj.base2 :: exibe();
// obj.exibe();  erro de compilação. Usar qual exibe??
}
Download

classe-base