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

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

Vamos abordar o exemplo Assumimos que se pretende declarar uma classe que se chama pessoa (de notar que uma classe semelhante foi considerada na aula anterior):

Apresentações semelhantes


Apresentação em tema: "Vamos abordar o exemplo Assumimos que se pretende declarar uma classe que se chama pessoa (de notar que uma classe semelhante foi considerada na aula anterior):"— Transcrição da apresentação:

1 Vamos abordar o exemplo Assumimos que se pretende declarar uma classe que 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 monitor Nós precisamos de usar esta função mas ela não é significativa neste contexto e por isso vai ser considerada posteriormente Este é o construtor Este é o destrutor

2 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 Idade Nome A classe aluno foi derivada da classe pessoa Consideremos o seguinte programa constituído por duas funções main e print_all:

3 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 objectos da classe pessoa Quanto é uma constante que, por exemplo, pode ser definida da seguinte forma: #define Quanto 3 4. O primeiro ponteiro muito[0] vai ser preenchido com o 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 considerada na próxima página

4 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; }

5 void print_all(pessoa** ponteiro_para_pessoa, int size) {int i=0; while (i print_me(); } } ** significa ponteiro_para_pessoa Array de ponteiros ponteiro0 ponteiro1 ponteiro2 etc. objecto do tipo pessoa Podem ser dos objectos derivados da classe pessoa

6 void print_all(pessoa** ponteiro_para_pessoa, int size) {int i=0; while (i print_me(); } } Esta função imprime os dados para todos os objectos que podem ser 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 ou um ponteiro para pessoa ou um ponteiro para aluno que é o tipo derivado do tipo pessoa

7 Vocês devem compreender que: 1. A variável ponteiro_para_pessoa[índice] é um nome que pode possuir valores diferentes. 2. Se ponteiro_para_pessoa[índice] tem um valor do ponteiro para o objecto do tipo pessoa, ele permite aceder a este objecto na memória, por exemplo: memória O objecto do tipo pessoa Nome Idade

8 3. Se ponteiro_para_pessoa tem um valor do ponteiro para o objecto do tipo aluno (que foi derivado da pessoa), ele permite o acesso a este objecto na memória, por exemplo: Nome Idade grupo Memória O objecto do tipo aluno

9 void print_all(pessoa** ponteiro_para_pessoa, int size) {int i=0; while (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;

10 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 - 25 Nome - Ricardo; Idade - 21 grupo 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);

11 Podemos concluir o seguinte: 1. A função print_all pode ser usada para a visualização no monitor dos dados de qualquer objecto da classe pessoa (ou da classe derivada da classa pessoa, por exemplo da classe aluno). 2. Se declaramos qualquer nova classe derivada da classe pessoa (por exemplo empregado) podemos imprimir os respectivos dados sem redefinição da função print_all. 3. Isto permite expandir as possibilidades do programa sem redefinição do seu código. Por outras palavras, podemos usar o mesmo código mesmo em tarefas novas. 4. Isto é impossível sem a utilização de herança.

12 A relação da herança pode ser designada da seguinte forma gráfica: pessoa aluno empregado Isto significa que a classe aluno é derivada da classe pessoa A classe base A classe derivada Podemos usar as mesmas regras para definir a outra classe derivada, por exemplo empregado. O código desta classe pode ser:

13 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 classe pessoa. Esta notação chama-se full qualified name (qualificador de nome completo)

14 void print_all(pessoa** ponteiro_para_pessoa, int size) {int i=0; while (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", ); 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", ); muito[2]=&e; 7. i=2; 8. ponteiro_para_pessoa[2]; 9. print_me() para empregado;

15 Nome - Paulo; Idade - 25 Nome - Ricardo; Idade - 21 grupo Nome - Nuno; Idade - 29 salário Nome - Nuno; Idade - 29 salário pessoa p(25,"Paulo"); aluno a(21, "Ricardo", 6251); empregado e(29, "Nuno", ); pessoa aluno empregado

16 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&);

17 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 classe base A classe derivada Esta função pode ser redefinida em classes derivadas e por isso foi declarada como uma função virtual virtual protected:

18 Polimorfismo representa um conceito na teoria de tipos no qual um único nome (como uma declaração de uma variável) pode denotar objectos de várias classes que se relacionam atravé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 em todas as linguagens que sejam strongly typed e statically bound

19 Linguagens tipificadas (typed), como o Pascal, são baseadas no conceito de que funções, procedimentos e operandos possuem um único tipo. Estas linguagens dizem-se monomórficas, no sentido de que qualquer valor ou variável pode ser interpretado como tendo um e um só tipo. Linguagens de programação monomórficas podem 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 significar coisas diferentes. Chamamos a este conceito overloading. Em C++ podemos declarar funções com nomes iguais, desde que as suas invocaçõ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.

20 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 e ligaçã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 distinguem a programação orientada por objectos da programação tradicional com tipos de dados abstractos.

21 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 ou pessoa& reference_to_pessoa ) significa referência para um valor do tipo TIPO. TIPO& o objecto pessoa &reference_to_pessoa ou pessoa& reference_to_pessoa pessoa &referência_to_pessoa Uma referência é um nome alternativo para o objecto Esta possibilidade vai ser considerada posteriormente com mais detalhe

22 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", ); print_ref(p); print_ref(a); print_ref(e);} Nome - Paulo; Idade - 25 Nome - Nuno; Idade - 29 salário Nome - Ricardo; Idade - 21 grupo p pessoa p(25,"Paulo"); a aluno a(21, "Ricardo", 6251); e empregado e(29, "Nuno", ); De notar que a função print_ref chama a mesma função print_me print_me Mas a invocação da função print_me depende do valor da reference_to_pessoa Isto é polimorfismo

23 int main(int argc, char* argv[]) { pessoa p(25,"Paulo"); aluno a(21, "Ricardo", 6251); empregado e(29, "Nuno", ); 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

24 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 e o 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 = Isto é polimorfismo

25 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ção Vamos considerar o seguinte código: int main(int argc, char* argv[]) { aluno a(21, "Ricardo", 6251); empregado e(29, "Nuno", ); int integer=12345, integer1=5; cout << "difference in integers === " << integer-integer1 << endl; cout << "difference in age === " << (e-a) << endl; return 0;} difference in integers === difference in age === 8 Esta função vai ser chamada - - esto é e-a Isto é sobrecarga de operações e também polimorfismo

26 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 Estar apto a construir programas triviais que utilizem encapsulamento, herança e polimorfismo.


Carregar ppt "Vamos abordar o exemplo Assumimos que se pretende declarar uma classe que se chama pessoa (de notar que uma classe semelhante foi considerada na aula anterior):"

Apresentações semelhantes


Anúncios Google