Programar em C++/Polimorfismo
Esta página precisa ser reciclada (discuta). Ao melhorá-la, você estará ajudando o Wikilivros. |
Conceito
[editar | editar código-fonte]Polimorfismo em linguagens orientadas a objeto, é a capacidade de objetos se comportarem de forma diferenciada em face de suas características ou do ambiente ao qual estejam submetidos, mesmo quando executando ação que detenha, semanticamente, a mesma designação.
O polimorfismo em C++ se apresenta sob diversas formas diferentes, desde as mais simples, como funções com mesmo nome e lista de parâmetros diferentes, até as mais complexas como funções virtuais, cujas formas de execução são dependentes da classe a qual o objeto pertence e são identificadas em tempo de execução.
Funções virtuais
[editar | editar código-fonte]#include <iostream>
using std::cout;
using std::endl;
class Base {
public:
// declaração da função virtual
virtual void Quem_VIRTUAL()
{
cout << "Base\n";
}
// função comum
void Quem_NAO_VIRTUAL()
{
cout << "Base\n";
}
};
class Derivada : public Base {
public:
// função virtual sobrescrita
virtual void Quem_VIRTUAL()
{
cout << "Derivada\n";
}
// função comum sobrescrita
void Quem_NAO_VIRTUAL()
{
cout << "Derivada\n";
}
};
int main ()
{
Base *ptr_base;
Derivada derivada;
ptr_base = &derivada; // conversão implícita permissível
ptr_base->Quem_VIRTUAL(); // chamada polimórfica (mostra: "Derivada")
ptr_base->Quem_NAO_VIRTUAL(); // chamada comum, não-polimórfica (mostra: "Base")
cout << endl;
return 0;
}
Chamando múltiplas funções virtuais
[editar | editar código-fonte]Funções virtuais e passagem por valor
[editar | editar código-fonte]Construtor de cópia virtual
[editar | editar código-fonte]Classe base virtual
[editar | editar código-fonte]Consideremos o seguinte programa:
// Este programa contém um erro e não será compilado.
#include <iostream>
using namespace std;
class base
{
public:
int i;
};
class derived1 : public base // derived1 inherits base.
{
public:
int j;
};
class derived2 : public base // derived2 inherits base.
{
public:
int k;
};
/*
* "derived3" herda características de "derived1" e "derived2".
* Isto significa que há duas cópias da base em "derived3"!
*/
class derived3 : public derived1, public derived2
{
public:
int sum;
};
int main()
{
derived3 ob;
ob.i = 10; // Isto se torna ambíguo; A qual "i" estamos nos referindo???
ob.j = 20;
ob.k = 30;
ob.sum = ob.i + ob.j + ob.k;// "i" ambíguo aqui, também
cout << ob.i << " ";// também ambíguo, Qual "i"?
cout << ob.j << " " << ob.k << " ";
cout << ob.sum;
#ifdef WIN32
system ("pause");
#endif
return 0;
}
As classes derived1 e derived2 são herdadas como classes base. A classe derived3 herda tanto de derived1 quanto de derived2. Como resultado temos 2 cópias da classe base presentes no objeto da derived3, por exemplo presente na linha ob.i=10; isto resulta numa ambiguidade e o programa não vai compilar.
Há duas maneiras para remediar a situação:
1. Aplicar o operador de resolução de escopo manualmente:
//Este programa usa resolução de escopo explicita para selecionar "i".
#include <iostream>
using namespace std;
class base
{
public:
int i;
};
class derived1 : public base // derived1 inherits base.
{
public:
int j;
};
class derived2 : public base // derived2 inherits base.
{
public:
int k;
};
class derived3 : public derived1, public derived2 /* "derived3" herda as bases "derived1" e "derived2". Isto significa que há duas cópias de bases em "derived3"! */
{
public:
int sum;
};
int main()
{
derived3 ob;
ob.derived1::i = 10; // escopo resolvido, usa o "i" em "derived1".
ob.j = 20;
ob.k = 30;
ob.sum = ob.derived1::i + ob.j + ob.k; // escopo resolvido.
cout << ob.derived1::i << " "; // também resolvido aqui.
cout << ob.j << " " << ob.k << " ";
cout << ob.sum;
#ifdef WIN32
system ("pause");
#endif
return 0;
}
2. A segunda maneira é através de classes bases virtuais:
Quando temos 2 ou mais objetos que são derivados da mesma base class, podemos prevenir múltiplas cópias da base class declarando a base class como virtual quando ela é herdada. Exemplificando:
// Este program usa classes bases virtuais.
#include <iostream>
using namespace std;
class base
{
public:
int i;
};
class derived1 : virtual public base // derived1 inherits base as virtual.
{
public:
int j;
};
class derived2 : virtual public base // derived2 inherits base as virtual.
{
public:
int k;
};
class derived3 : public derived1, public derived2 /* derived3 inherits both derived1 and derived2. This time, there is only one copy of base class. */
{
public:
int sum;
};
int main()
{
derived3 ob;
ob.i = 10; // now unambiguous
ob.j = 20;
ob.k = 30;
ob.sum = ob.i + ob.j + ob.k;// unambiguous
cout << ob.i << " ";// unambiguous
cout << ob.j << " " << ob.k << " ";
cout << ob.sum;
system ("pause");
return 0;
}
Repare que agora temos a palavra virtual antes da classe.