Vamos abordar o exemplo Assumimos que se pretende declarar uma classe que se chama pessoa (de notar...
Transcript of Vamos abordar o exemplo Assumimos que se pretende declarar uma classe que se chama pessoa (de notar...
Vamos abordar o exemplo
Assumimos que se pretende declarar uma classeque se chama “pessoa” (de notar que uma classe semelhante foi
considerada na aula anterior):
class pessoa { unsigned short Idade;
char* Nome;public:
pessoa(unsigned short Id=0, char* No="");virtual ~pessoa();virtual void print_me();const pessoa& operator =(const pessoa&);
};
Esta funçãao será utilizada para a visualização dos dados no monitorNós precisamos de usar esta função mas ela não é significativa
neste contexto e por isso vai ser consideradaposteriormente
Este é o construtor
Este é o destrutor
Vamos assumir que nós criámos uma classe derivada da classe pessoa,por exemplo:
class aluno : public pessoa { int grupo;public:
void print_me();aluno(unsigned short, char*, int);virtual ~aluno();const aluno& operator =(const aluno& pes);
};
Este é o número do grupo do aluno
Esta função será utilizada para a visualização dos dados no monitor
IdadeNome
A classe aluno foi derivada da classe pessoa
Consideremos o seguinte programa constituído por duas funçõesmain e print_all:
int main(int argc, char* argv[]){ pessoa p(25,"Paulo");
aluno a(21, "Ricardo", 6251);p.print_me();pessoa* muito[Quanto];muito[0]=&p;muito[1]=&a;print_all(muito,Quanto);return 0;
}
O programa main realiza das seguintes acções:1. Declara dois objectos, que são p do tipo pessoa e a do tipo aluno;
2. Executa a função p.print_me para o objecto p;
3. Declara array que é composto por ponteiros para objectosda classe pessoa
“Quanto” é umaconstante que, por exemplo,pode ser definida da seguinte forma:#define Quanto 3
4. O primeiro ponteiro “muito[0]” vai ser preenchido como valor &p que é o ponteiro para o objecto “p” do tipo pessoa.
5. O segundo ponteiro “muito[1]” vai ser preenchido com o valor &a que é o ponteiro para o objecto “a” do tipo aluno.
6. Executa a função print_all que vai ser consideradana próxima página
int main(int argc, char* argv[]){ pessoa p(25,"Paulo");
aluno a(21, "Ricardo", 6251);p.print_me();pessoa* muito[Quanto];muito[0]=&p;muito[1]=&a;print_all(muito,Quanto);return 0;
}
void print_all(pessoa** ponteiro_para_pessoa, int size){ int i=0;
while (i<size) { ponteiro_para_pessoa[i++]->print_me(); }}
** significa
ponteiro_para_pessoa
Array de ponteiros
ponteiro0
ponteiro1
ponteiro2
etc.
objecto do tipo pessoa
objecto do tipo pessoa
objecto do tipo pessoa
objecto do tipo pessoa
Podem ser dosobjectos derivados
da classe pessoa
void print_all(pessoa** ponteiro_para_pessoa, int size){ int i=0;
while (i<size) { ponteiro_para_pessoa[i++]->print_me(); }}
Esta função imprime os dados para todos os objectos que podemser determinados através dos respectivos ponteiros.
Idade,Nome
Idade,Nome,grupo
Isto pode ser feito com a ajuda da função print_me
Já vimos que o ponteiro_para_pessoa pode ser ouum ponteiro para pessoa ou um ponteiro para aluno que é o tipo
derivado do tipo pessoa
Vocês devem compreender que:
1. A variável ponteiro_para_pessoa[índice] é um nome que podepossuir valores diferentes.
2. Se ponteiro_para_pessoa[índice] tem um valor do ponteiro para oobjecto do tipo pessoa, ele permite aceder a este objecto na memória,por exemplo:
memória
O objectodo tipo pessoa
NomeIdade
3. Se ponteiro_para_pessoa tem um valor do ponteiro para o objectodo tipo aluno (que foi derivado da pessoa), ele permite o acessoa este objecto na memória, por exemplo:
NomeIdadegrupo
Memória
O objectodo tipo aluno
void print_all(pessoa** ponteiro_para_pessoa, int size){ int i=0;
while (i<size) { ponteiro_para_pessoa[i++]->print_me(); }}
Idade,Nome
Idade,Nome,grupo
pessoa p(25,"Paulo");aluno a(21, "Ricardo", 6251);p.print_me();pessoa* muito[Quanto];muito[0]=&p;muito[1]=&a;print_all(muito,Quanto);
Vamos abordar o seguinte código: 1. i=0; 2. ponteiro_para_pessoa[0];
3. print_me() para pessoa;
5. ponteiro_para_pessoa[1];
4. i=1;
6. print_me() para aluno;
Agora vamos considerar a função print_me:
void pessoa::print_me(){ cout << "Nome - " << Nome << "; Idade - " << Idade << endl;}
void aluno::print_me(){ pessoa::print_me(); cout << "grupo - " << grupo << endl;}
Nome - Paulo; Idade - 25Nome - Ricardo; Idade - 21grupo - 6251
Nome = “Paulo”
Idade = 25
saltar na próxima linha
void pessoa::print_me(){ cout << "Nome - " << Nome << "; Idade - " << Idade << endl;}
grupo = 6251
Nome - Ricardo; Idade - 21
pessoa p(25,"Paulo");aluno a(21, "Ricardo", 6251);
Podemos concluir o seguinte:
1. A função print_all pode ser usada para a visualização nomonitor dos dados de qualquer objecto da classe pessoa (ouda classe derivada da classa pessoa, por exemplo da classe aluno).
2. Se declaramos qualquer nova classe derivada da classepessoa (por exemplo empregado) podemos imprimir os respectivosdados sem redefinição da função print_all.
3. Isto permite expandir as possibilidades do programa semredefinição do seu código. Por outras palavras, podemos usaro mesmo código mesmo em tarefas novas .
4. Isto é impossível sem a utilização de herança.
A relação da herança pode ser designada da seguinte formagráfica:
pessoa
aluno empregado
Isto significa que a classe aluno é derivada da classe pessoa
A classe base
A classe derivada A classe derivada
Podemos usar as mesmas regras para definir a outra classe derivada,por exemplo empregado.
O código desta classe pode ser:
class empregado : public pessoa { unsigned long salario;public:
empregado(unsigned short, char*, unsigned long);virtual ~empregado();void print_me();const empregado& operator =(const empregado& pes);
};
void empregado::print_me(){
pessoa::print_me();cout << "salario - " << salario << endl;
}
Isto significa que a função print_me deve ser chamada para a classepessoa. Esta notação chama-se full qualified name
(qualificador de nome completo)
void print_all(pessoa** ponteiro_para_pessoa, int size){ int i=0;
while (i<size) { ponteiro_para_pessoa[i++]->print_me(); }}
Idade,Nome
Idade,Nome,grupo
pessoa p(25,"Paulo");aluno a(21, "Ricardo", 6251);p.print_me();pessoa* muito[Quanto];muito[0]=&p;muito[1]=&a;
empregado e(29, "Nuno", 180000); muito[2]=&e;
print_all(muito,Quanto);
Vamos abordar o seguinte código: 1. i=0; 2. ponteiro_para_pessoa[0];
3. print_me() para pessoa;
5. ponteiro_para_pessoa[1];
4. i=1;
6. print_me() para aluno;
Idade,Nome,salario
empregado e(29, "Nuno", 180000); muito[2]=&e;
7. i=2; 8. ponteiro_para_pessoa[2];
9. print_me() paraempregado;
Nome - Paulo; Idade - 25Nome - Ricardo; Idade - 21grupo - 6251
Nome - Nuno; Idade - 29salário - 180000Nome - Nuno; Idade - 29salário - 180000
pessoa p(25,"Paulo");
aluno a(21, "Ricardo", 6251);
empregado e(29, "Nuno", 180000);pessoa
aluno empregado
class pessoa { unsigned short Idade;
char* Nome;public:
pessoa(unsigned short Id=0, char* No="");~pessoa();virtual void print_me();const pessoa& operator =(const pessoa&);
};
unsigned short Idade;char* Nome;
public:pessoa(unsigned short Id=0, char* No="");~pessoa();virtual void print_me();const pessoa& operator =(const pessoa&);
class empregado : public pessoa { unsigned long salario;public:
empregado(unsigned short, char*, unsigned long);~empregado();void print_me();const empregado& operator =(const empregado& pes);
};
class pessoa { unsigned short Idade;
char* Nome;public:
pessoa(unsigned short Id=0, char* No="");~pessoa();virtual void print_me();const pessoa& operator =(const pessoa&);
};
unsigned short Idade;char* Nome;
public:pessoa(unsigned short Id=0, char* No="");~pessoa();virtual void print_me();const pessoa& operator =(const pessoa&);
A classebase
A classe derivadaEsta função pode ser redefinida em classes derivadas e por issofoi declarada como uma função virtual
virtual
protected:
Polimorfismo representa um conceito na teoria de tipos no qualum único nome (como uma declaração de uma variável) pode
denotar objectos de várias classes que se relacionamatravés de uma superclasse comum.
Qualquer objecto que possua esse nome está apto a responder a um conjunto comum de operações.
O oposto de polimorfismo é monomorfismo, que se encontra emtodas as linguagens que sejam strongly typed e statically bound
Linguagens tipificadas (typed), como o Pascal, são baseadas noconceito de que funções, procedimentos e operandos possuem umúnico tipo. Estas linguagens dizem-se monomórficas, no sentidode que qualquer valor ou variável pode ser interpretado como
tendo um e um só tipo. Linguagens de programação monomórficaspodem contrastar com linguagens polimórficas, nas quais alguns
valores e variáveis podem ter mais do que um tipo
Um símbolo, por exemplo "+", pode ser definido para significarcoisas diferentes. Chamamos a este conceito overloading. Em C++
podemos declarar funções com nomes iguais, desde que as suasinvocações possam ser distinguidas pelas suas assinaturas, que
consistem no número e tipo dos seus argumentos
Herança sem polimorfismo é possível,mas certamente que não é muito útil.
Em C++ o polimorfismo é expresso através dos conceitos de 1) funções virtuais e 2) overloading
O polimorfismo existe quando as características de herança eligação dinâmica interagem. É talvez a característica mais
poderosa das linguagens de programação orientada por objectos.
Polimorfismo e herança são características que distinguema programação orientada por objectos
da programação tradicional com tipos de dados abstractos.
Vamos abordar o exemplo:
void print_ref(pessoa &reference_to_pessoa){
reference_to_pessoa.print_me();}
A notação o TIPO& o objecto(por exemplo
pessoa &reference_to_pessoa oupessoa& reference_to_pessoa
)significa referência para um valor do tipo TIPO.
TIPO& o objecto
pessoa &reference_to_pessoa oupessoa& reference_to_pessoa
pessoa &referência_to_pessoa
Uma referência é um nome alternativo para o objecto
Esta possibilidade vai ser considerada posteriormentecom mais detalhe
void print_ref(pessoa &reference_to_pessoa){
reference_to_pessoa.print_me();}
A função print_ref pode ser usada da seguinte maneira:
int main(int argc, char* argv[]){ pessoa p(25,"Paulo");
aluno a(21, "Ricardo", 6251);empregado e(29, "Nuno", 180000);print_ref(p);print_ref(a);print_ref(e); }Nome - Paulo; Idade - 25
Nome - Nuno; Idade - 29salário ‘ 180000
Nome - Ricardo; Idade - 21grupo - 6251
p
pessoa p(25,"Paulo");
a
aluno a(21, "Ricardo", 6251);
e
empregado e(29, "Nuno", 180000);
De notar que a função print_refchama a mesma função print_me
print_me
Mas a invocação da função print_me depende do valor dareference_to_pessoa
Isto é polimorfismo
int main(int argc, char* argv[]){ pessoa p(25,"Paulo"); aluno a(21, "Ricardo", 6251); empregado e(29, "Nuno", 180000); print_ref(p); print_ref(a); print_ref(e); }
void print_ref(pessoa &reference_to_pessoa){ reference_to_pessoa.print_me(); }
void pessoa::print_me(){ cout << "Nome - " << Nome << "; Idade - " << Idade << endl; }
void aluno::print_me(){ pessoa::print_me(); cout << "grupo - " << grupo << endl; }
void empregado::print_me(){ pessoa::print_me(); cout << "salario - " << salario << endl; }
Sumário
void print_ref(pessoa &reference_to_pessoa){ reference_to_pessoa.print_me(); }
void print_ref(int &i){ cout << "i = " << i << endl; }
Vamos considerar as duas seguintes funções que tem a mesmo nome
Mas o argumento da primeira função é do tipo pessoa eo argumento da segunda função é do tipo int e
assumimos que temos o seguinte codico
int main(int argc, char* argv[]){ pessoa p(25,"Paulo");
int integer=12345;print_ref(p);print_ref(integer);return 0; }
Nome - Paulo; Idade - 25
i = 12345
Isto é polimorfismo
Consideremos a seguinte função:
int operator-(const pessoa& reference_to_pessoa2){ int temp=Idade - reference_to_pessoa2.Idade;
return temp;}
Este é o nome da funçãoVamos considerar o seguinte código:int main(int argc, char* argv[]){ aluno a(21, "Ricardo", 6251); empregado e(29, "Nuno", 180000); int integer=12345, integer1=5; cout << "difference in integers === " << integer-integer1 << endl; cout << "difference in age === " << (e-a) << endl; return 0; }
difference in integers === 12340difference in age === 8
Esta função vaiser chamada
--esto é e-a
Isto é sobrecarga deoperações e também
polimorfismo
O que é importante:
1. Perceber o que são paradigmas de programação.
2. Perceber mais detalhes sobre encapsulamento.
3. Perceber o que é herança.
4. Perceber o que é um polimorfismo.
5. Perceber as regras da linguagem C++.
6. Estar apto a construir programas triviais que utilizem encapsulamento, herança e polimorfismo.