No Slide Title - Páginas Pessoais

Propaganda
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
Este é o construtor
{
unsigned short Idade;
char* Nome;
public:
pessoa(unsigned short Id=0, char* No="");
virtual ~pessoa();
Este é o destrutor
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
Vamos assumir que nós criámos uma classe derivada da classe pessoa,
por exemplo:
class aluno : public pessoa
Este é o número do grupo do aluno
{
int grupo;
public:
void print_me();
Idade
aluno(unsigned short, char*, int);
Nome
virtual ~aluno();
const aluno& operator =(const aluno& pes);
};
Esta função será utilizada para a visualização dos dados no monitor
A classe aluno foi derivada da classe pessoa
Consideremos o seguinte programa constituído por duas funções
main e print_all:
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
int main(int argc, char* argv[])
4. O primeiro
“muito[0]”
vai ser preenchido com
{ ponteiro
pessoa
p(25,"Paulo");
o valor &p que é o aluno
ponteiro
para
o objecto6251);
“p” do tipo pessoa.
a(21,
"Ricardo",
p.print_me();
5. O segundo ponteiro
“muito[1]” vai ser preenchido com
pessoa* muito[Quanto];
o valor &a que é o ponteiro
para o objecto “a” do tipo aluno.
muito[0]=&p;
“Quanto” é uma
muito[1]=&a;
constante que, por exemplo,
print_all(muito,Quanto);
pode ser definida da
return 0;
seguinte forma:
}
3
6. Executa a função print_all #define
que vai Quanto
ser considerada
na 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
Array de ponteiros
ponteiro_para_pessoa
Podem ser dos
objectos derivados
da classe pessoa
ponteiro0
ponteiro1
objecto do tipo pessoa
objecto do tipo pessoa
ponteiro2
objecto do tipo pessoa
objecto do tipo pessoa
etc.
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 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
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
Nome
Idade
O objecto
do tipo pessoa
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
void print_all(pessoa** ponteiro_para_pessoa, int size)
{
int i=0;
while (i<size) { ponteiro_para_pessoa[i++]->print_me(); }
}
Vamos abordar o seguinte código:
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);
Idade,
Nome
Idade,
Nome,
grupo
1. i=0;
2. ponteiro_para_pessoa[0];
3. print_me() para pessoa;
4. i=1;
5. ponteiro_para_pessoa[1];
6. print_me() para aluno;
Agora vamos considerar a função print_me:
void pessoa::print_me()
Nome = “Paulo”
{
cout << "Nome - " << Nome
Idade = 25
<< "; Idade - " << Idade << endl;
}
pessoa p(25,"Paulo");
aluno a(21, "Ricardo", 6251);
void aluno::print_me()
saltar na próxima linha
{
pessoa::print_me();
cout << "grupo - " << grupo << endl;
grupo = 6251
}
Nome - Paulo; Idade - 25
Nome - Ricardo; Idade - 21
grupo - 6251
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.
A relação da herança pode ser designada da seguinte forma
gráfica:
pessoa
A classe derivada
aluno
A classe base
A classe derivada
empregado
Isto significa que a classe aluno é derivada da classe pessoa
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 classe
pessoa. 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(); }
}
Vamos abordar o seguinte código:
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;
muito[2]=&e;
print_all(muito,Quanto);
Idade,
Idade,
Idade,
Nome,
Nome,
Nome
salario
grupo
1. i=0;
2. ponteiro_para_pessoa[0];
3. print_me() para pessoa;
4. i=1;
5. ponteiro_para_pessoa[1];
6. print_me() para aluno;
7. i=2;
8. ponteiro_para_pessoa[2];
9. print_me() para
empregado;
Nome - Paulo; Idade - 25
pessoa p(25,"Paulo");
Nome - Ricardo; Idade - 21
grupo - 6251
aluno a(21, "Ricardo", 6251);
Nome - Nuno; Idade - 29
salário - 180000
empregado e(29, "Nuno", 180000);
pessoa
aluno
empregado
class pessoa
{
unsigned
short
Idade;
unsigned
short
Idade;
char*
Nome;
char*
Nome;
public:
public:
pessoa(unsignedshort
shortId=0,
Id=0,char*
char*No="");
No="");
pessoa(unsigned
~pessoa();
~pessoa();
virtualvoid
voidprint_me();
print_me();
virtual
constpessoa&
pessoa&operator
operator=(const
=(constpessoa&);
pessoa&);
const
};
class pessoa
protected:
{
unsigned
short
Idade;
unsigned
short
Idade;
char*
Nome;
char*
Nome;
public:
public:
pessoa(unsigned
pessoa(unsignedshort
shortId=0,
Id=0,char*
char*No="");
No="");
~pessoa();
~pessoa();
virtual
virtualvoid
voidprint_me();
print_me();
const
constpessoa&
pessoa&operator
operator=(const
=(constpessoa&);
pessoa&);
};
A classe
base
classederivadas
derivada e por isso
Esta função pode ser redefinida em A
classes
foi declarada como uma função virtual
class empregado : public pessoa
{
unsigned long salario;
public:
empregado(unsigned short, char*, unsigned long);
~empregado();
void print_me();
const empregado& operator =(const empregado& pes);
};
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
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.
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.
Esta possibilidade
vaiabordar
ser considerada
posteriormente
Vamos
o exemplo:
com mais detalhe
pessoa &referência_to_pessoa
void print_ref(pessoa
&reference_to_pessoa)
{
reference_to_pessoa.print_me();
}
TIPO& oo objecto
objecto
A notação o TIPO&
(por exemplo
pessoa &reference_to_pessoa
&reference_to_pessoa ou
ou
pessoa
pessoa& reference_to_pessoa
reference_to_pessoa
pessoa&
)
significa referência para um valor do tipo TIPO.
Uma referência é um nome alternativo para o objecto
void print_ref(pessoa &reference_to_pessoa)
{
reference_to_pessoa.print_me();
print_me
}
Mas a invocação da função print_me depende do valor da
A função print_ref podereference_to_pessoa
ser usada da seguinte maneira:
int main(int argc, char* argv[]) De notar que a função print_ref
chama a mesma função print_me
{
pessoa p(25,"Paulo");
aluno a(21, "Ricardo", 6251);
empregado e(29, "Nuno", 180000);
p
print_ref(p);
a
print_ref(a);
Nome - Paulo;
Idade - 25
e
print_ref(e);
}
Nome - Ricardo; Idade - 21
grupo - 6251
Nome - Nuno; Idade - 29
salário ‘ 180000
Isto é polimorfismo
void print_ref(pessoa &reference_to_pessoa)
{
reference_to_pessoa.print_me(); }
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);
}
Sumário
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; }
Vamos considerar as duas seguintes funções que tem a mesmo nome
void print_ref(pessoa &reference_to_pessoa)
{
reference_to_pessoa.print_me(); }
void print_ref(int &i)
{
cout << "i = " << i << endl; }
Isto é polimorfismo
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 = 12345
Consideremos a seguinte função:
int operator-(const pessoa& reference_to_pessoa2)
{
int temp=Idade - reference_to_pessoa2.Idade;
return temp;
}
Vamos considerar o seguinte código:
é o nome
dachar*
função
intEste
main(int
argc,
argv[])
{ aluno a(21, "Ricardo", 6251);
empregado e(29, "Nuno", 180000);
int integer=12345, integer1=5;
cout << "difference in integers === "
<< integer-integer1 << endl;
esto
cout << "difference in age === " << (e-a) << endl;
return 0; }
Isto é sobrecarga
devai
Esta função
ser chamada
operações e também
polimorfismodifference in integers === 12340
difference in age === 8
é e-a
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.
Download