C++ Polimorfismo com Exemplo
โก Resumo Inteligente
Polimorfismo em C++ Permite que uma รบnica funรงรฃo membro assuma vรกrias formas, comportando-se de maneira diferente dependendo do objeto que a invoca. Baseia-se em heranรงa e aparece em duas variantes, resolvidas em tempo de compilaรงรฃo ou em tempo de execuรงรฃo.

O que รฉ polimorfismo em C++?
In C++O polimorfismo faz com que uma funรงรฃo membro se comporte de maneira diferente dependendo do objeto que a chama/invoca. Polimorfismo รฉ uma palavra grega que significa ter muitas formas. Ele ocorre quando vocรช tem uma hierarquia de funรงรตes membro. aulas relacionados por heranรงa.
Por exemplo, suponha que temos a funรงรฃo makeSound(). Quando um gato chama esta funรงรฃo, ele produz o som de miado. Quando uma vaca invoca a mesma funรงรฃo, ela emitirรก o som moow.
Embora tenhamos uma funรงรฃo, ela se comporta de maneira diferente em circunstรขncias diferentes. A funรงรฃo tem vรกrios formatos; portanto, alcanรงamos o polimorfismo.
Com a ideia central definida, C++ Organiza esse comportamento em duas categorias distintas.
Tipos de polimorfismo
C++ suporta dois tipos de polimorfismo:
- Polimorfismo em tempo de compilaรงรฃo e
- Polimorfismo de tempo de execuรงรฃo.
A primeira categoria resolve todas as chamadas de funรงรฃo antes mesmo de o programa ser executado.
Polimorfismo de tempo de compilaรงรฃo
Vocรช invoca as funรงรตes sobrecarregadas combinando o nรบmero e o tipo de argumentos. A informaรงรฃo estรก presente durante o tempo de compilaรงรฃo. Isto significa o C++ o compilador selecionarรก a funรงรฃo correta em tempo de compilaรงรฃo.
O polimorfismo em tempo de compilaรงรฃo รฉ obtido por meio da sobrecarga de funรงรตes e da sobrecarga de operadores.
Sobrecarga de funรงรฃo
A sobrecarga de funรงรตes ocorre quando temos muitas funรงรตes com nomes semelhantes, mas argumentos diferentes. Os argumentos podem diferir em termos de nรบmero ou tipo.
Exemplo 1
#include <iostream> using namespace std; void test(int i) { cout << " The int is " << i << endl; } void test(double f) { cout << " The float is " << f << endl; } void test(char const *ch) { cout << " The char* is " << ch << endl; } int main() { test(5); test(5.5); test("five"); return 0; }
Saรญda:
Aqui estรก uma captura de tela do cรณdigo:
Code Explicaรงรฃo:
- Inclua o arquivo de cabeรงalho iostream em nosso cรณdigo. Poderemos usar suas funรงรตes.
- Inclua o namespace std em nosso cรณdigo. Poderemos usar suas classes sem chamรก-lo.
- Crie uma funรงรฃo chamada test que receba um parรขmetro inteiro i. O {marca o inรญcio do corpo do teste de funรงรฃo.
- Instruรงรฃo a ser executada se o teste de funรงรฃo acima for invocado/chamado.
- Fim do corpo do teste de funรงรฃo acima.
- Crie uma funรงรฃo chamada test que receba um parรขmetro flutuante f. O {marca o inรญcio do corpo do teste de funรงรฃo.
- Instruรงรฃo a ser executada se o teste de funรงรฃo acima for invocado/chamado.
- Fim do corpo do teste de funรงรฃo acima.
- Crie uma funรงรฃo chamada test que receba um parรขmetro de caractere ch. O {marca o inรญcio do corpo do teste de funรงรฃo.
- Instruรงรฃo a ser executada se o teste de funรงรฃo acima for invocado/chamado.
- Fim do corpo do teste de funรงรฃo acima.
- Chame a funรงรฃo main(). O { marca o inรญcio do corpo da funรงรฃo.
- Chame a funรงรฃo test e passe 5 para ela como o valor do argumento. Isto invoca a funรงรฃo de teste que aceita um argumento inteiro, ou seja, a primeira funรงรฃo de teste.
- Chame a funรงรฃo test e passe 5.5 para ela como o valor do argumento. Isto invocarรก a funรงรฃo de teste que aceita um argumento float, ou seja, a segunda funรงรฃo de teste.
- Chame a funรงรฃo test e passe cinco para ela como o valor do argumento. Isto invocarรก a funรงรฃo de teste que aceita um argumento de caractere, ou seja, a terceira funรงรฃo de teste.
- O programa deverรก retornar um valor se for executado com sucesso.
- O final do corpo da funรงรฃo main().
Temos trรชs funรงรตes com o mesmo nome, mas diferentes tipos de argumentos. Alcanรงamos o polimorfismo.
Operasobrecarga
In Operator Sobrecarga, definimos um novo significado para um C++ operadorIsso tambรฉm altera o funcionamento do operador. Por exemplo, podemos definir o operador + para concatenar duas strings. Conhecemos esse operador como o operador de adiรงรฃo para somar valores numรฉricos. Apรณs nossa definiรงรฃo, quando colocado entre nรบmeros inteiros, ele os somarรก. Quando colocado entre strings, ele as concatenarรก.
Exemplo 2
#include<iostream> using namespace std; class ComplexNum { private: int real, over; public: ComplexNum(int rl = 0, int ov = 0) { real = rl; over = ov; } ComplexNum operator + (ComplexNum const &obj) { ComplexNum result; result.real = real + obj.real; result.over = over + obj.over; return result; } void print() { cout << real << " + i" << over << endl; } }; int main() { ComplexNum c1(10, 2), c2(3, 7); ComplexNum c3 = c1+c2; c3.print(); }
Saรญda:
Aqui estรก uma captura de tela do cรณdigo:
Code Explicaรงรฃo:
- Inclua o arquivo de cabeรงalho iostream em nosso programa para usar suas funรงรตes.
- Inclua o namespace std em nosso programa para usar suas classes sem chamรก-lo.
- Crie uma classe chamada ComplexNum. O { marca o inรญcio do corpo da classe.
- Use o modificador de acesso privado para marcar variรกveis โโcomo privadas, o que significa que elas sรณ podem ser acessadas dentro da classe.
- Defina duas variรกveis โโinteiras, reais e superiores.
- Use o modificador de acesso `public` para marcar o construtor como pรบblico, o que significa que ele serรก acessรญvel mesmo de fora da classe.
- Crie o construtor da classe e inicialize as variรกveis.
- Inicialize o valor da variรกvel real.
- Inicialize o valor da variรกvel.
- Fim do corpo do construtor.
- Precisamos substituir o significado do operador +.
- Crie o tipo de dados resultado do tipo ComplexNum.
- Use o operador + com nรบmeros complexos. Esta linha adicionarรก a parte real de um nรบmero ร parte real de outro nรบmero.
- Use o operador + com nรบmeros complexos. Esta linha adicionarรก a parte imaginรกria de um nรบmero ร parte imaginรกria de outro nรบmero.
- O programa retornarรก o valor da variรกvel resultado apรณs a execuรงรฃo bem-sucedida.
- Fim da definiรงรฃo do novo significado do operador +, ou seja, sobrecarga.
- Chame o mรฉtodo print().
- Imprima o novo nรบmero complexo apรณs a adiรงรฃo no console.
- Fim do corpo da funรงรฃo print().
- Fim do corpo da classe ComplexNum.
- Chame a funรงรฃo main().
- Passe os valores das partes reais e complexas a serem somadas. A primeira parte de c1 serรก somada ร primeira parte de c2, ou seja, 10+3. A segunda parte de c1 serรก somada ร segunda parte de c, ou seja, 2+7.
- Execute uma operaรงรฃo usando o operador + sobrecarregado e armazenando o resultado na variรกvel c3.
- Imprima o valor da variรกvel c3 no console.
- Fim do corpo da funรงรฃo main().
Enquanto o polimorfismo em tempo de compilaรงรฃo decide cedo, a segunda categoria adia a escolha atรฉ a execuรงรฃo.
Polimorfismo de tempo de execuรงรฃo
Isso acontece quando o mรฉtodo de um objeto รฉ invocado/chamado durante o tempo de execuรงรฃo, e nรฃo durante o tempo de compilaรงรฃo. O polimorfismo de tempo de execuรงรฃo รฉ obtido por meio da substituiรงรฃo de funรงรตes. A funรงรฃo a ser chamada/invocada รฉ estabelecida durante o tempo de execuรงรฃo.
Substituiรงรฃo de funรงรฃo
A substituiรงรฃo de funรงรฃo ocorre quando uma funรงรฃo da classe base recebe uma nova definiรงรฃo em uma classe derivada. Nesse momento, podemos dizer que a funรงรฃo base foi substituรญda.
Por exemplo:
#include <iostream> using namespace std; class Mammal { public: void eat() { cout << "Mammals eat..."; } }; class Cow: public Mammal { public: void eat() { cout << "Cows eat grass..."; } }; int main(void) { Cow c = Cow(); c.eat(); return 0; }
Saรญda:
Aqui estรก uma captura de tela do cรณdigo:
Code Explicaรงรฃo:
- Importe o arquivo de cabeรงalho iostream para nosso programa para usar suas funรงรตes.
- Inclua o namespace std em nosso programa para usar suas classes sem chamรก-lo.
- Crie uma classe chamada Mamรญfero. O { marca o inรญcio do corpo da classe.
- Use o modificador de acesso pรบblico para definir a funรงรฃo que estamos prestes a criar como acessรญvel publicamente. Serรก acessรญvel de fora desta classe.
- Crie uma funรงรฃo pรบblica chamada comer. O { marca o inรญcio do corpo da funรงรฃo.
- Imprima a instruรงรฃo adicionada ร funรงรฃo cout quando a funรงรฃo eat() รฉ invocada.
- O final do corpo da funรงรฃo eat().
- Fim do corpo da classe Mamรญfero.
- Crie uma classe chamada Cow que herda a classe Mammal. Cow รฉ a classe derivada, enquanto Mammal รฉ a classe base. O { marca o inรญcio desta aula.
- Use o modificador de acesso pรบblico para marcar a funรงรฃo que estamos prestes a criar como acessรญvel publicamente. Serรก acessรญvel de fora desta classe.
- Substitua a funรงรฃo eat() que foi definida na classe base. O { marca o inรญcio do corpo da funรงรฃo.
- A instruรงรฃo a ser impressa no console quando esta funรงรฃo รฉ invocada.
- Fim do corpo da funรงรฃo comer().
- Fim do corpo da classe Vaca.
- Chame a funรงรฃo main(). O { marca o inรญcio do corpo desta funรงรฃo.
- Crie uma instรขncia da classe Cow e dรช a ela o nome c.
- Chame a funรงรฃo eat() definida na classe Cow.
- O programa deve retornar um valor apรณs a conclusรฃo bem-sucedida.
- Fim da funรงรฃo main().
C++ Funรงรฃo Virtual
Uma funรงรฃo virtual รฉ outra maneira de implementar o polimorfismo em tempo de execuรงรฃo em C++. ร uma funรงรฃo especial definida em uma classe base e redefinida na classe derivada. Para declarar uma funรงรฃo virtual, vocรช deve usar a palavra-chave virtual. A palavra-chave deve preceder a declaraรงรฃo da funรงรฃo na classe base.
Se uma classe de funรงรฃo virtual for herdada, a classe virtual redefine a funรงรฃo virtual para atender ร s suas necessidades. Por exemplo:
#include <iostream> using namespace std; class ClassA { public: virtual void show() { cout << "The show() function in base class invoked..." << endl; } }; class ClassB :public ClassA { public: void show() { cout << "The show() function in derived class invoked..."; } }; int main() { ClassA* a; ClassB b; a = &b; a->show(); }
Saรญda:
Aqui estรก uma captura de tela do cรณdigo:
Code Explicaรงรฃo:
- Inclua o arquivo de cabeรงalho iostream no cรณdigo para usar suas funรงรตes.
- Inclua o namespace std em nosso cรณdigo para usar suas classes sem chamรก-lo.
- Crie uma classe chamada ClassA.
- Use o modificador de acesso pรบblico para marcar um membro da classe como acessรญvel publicamente.
- Crie uma funรงรฃo virtual chamada show(). Serรก uma funรงรฃo pรบblica.
- O texto a ser impresso quando show() invocado รฉ invocado. O final รฉ um C++ palavra-chave, que significa linha final. Move o cursor do mouse para a prรณxima linha.
- Fim do corpo da funรงรฃo virtual show().
- Fim do corpo da classe ClassA.
- Criando uma nova classe chamada ClassB que herda a classe ClassA. ClassA se torna a classe base enquanto ClassB se torna a classe derivada.
- Use o modificador de acesso pรบblico para marcar um membro da classe como acessรญvel publicamente.
- Redefina a funรงรฃo virtual show() derivada na classe base.
- O texto a ser impresso no console quando a funรงรฃo show() definida na classe derivada รฉ invocada.
- Fim do corpo da funรงรฃo show().
- Fim do corpo da classe derivada, ClassB.
- Chame a funรงรฃo main(). A lรณgica do programa deve ser adicionada ao seu corpo.
- Crie uma variรกvel de ponteiro chamada a. Ele aponta para a classe chamada ClassA.
- Crie uma instรขncia da classe chamada ClassB. A instรขncia recebe o nome b.
- Atribua os valores armazenados no endereรงo b na variรกvel a.
- Invoque a funรงรฃo show() definida na classe derivada. A vinculaรงรฃo tardia foi implementada.
- Fim do corpo da funรงรฃo main().
Com ambos os mecanismos explicados, a tabela abaixo os compara lado a lado.
Polimorfismo em tempo de compilaรงรฃo vs. Polimorfismo em tempo de execuรงรฃo
Aqui estรฃo as principais diferenรงas entre os dois:
| Polimorfismo em tempo de compilaรงรฃo | Polimorfismo em tempo de execuรงรฃo |
|---|---|
| Tambรฉm รฉ chamado de ligaรงรฃo precoce ou polimorfismo estรกtico. | Tambรฉm รฉ chamado de ligaรงรฃo tardia/dinรขmica ou polimorfismo dinรขmico. |
| O mรฉtodo รฉ chamado/invocado durante o tempo de compilaรงรฃo | O mรฉtodo รฉ chamado/invocado durante o tempo de execuรงรฃo |
| Implementado por meio de sobrecarga de funรงรฃo e sobrecarga de operador | Implementado por meio de substituiรงรฃo de mรฉtodo e funรงรตes virtuais |
| Exemplo, sobrecarga de mรฉtodo. Muitos mรฉtodos podem ter nomes semelhantes, mas diferentes nรบmeros ou tipos de argumentos | Exemplo, substituiรงรฃo de mรฉtodo. Muitos mรฉtodos podem ter um nome semelhante e o mesmo protรณtipo. |
| Execuรงรฃo mais rรกpida, pois a descoberta de mรฉtodos รฉ feita durante a compilaรงรฃo. | Execuรงรฃo mais lenta, pois a descoberta de mรฉtodos รฉ feita em tempo de execuรงรฃo. |
| Less flexibilidade para resoluรงรฃo de problemas รฉ fornecida, pois tudo รฉ conhecido durante o tempo de compilaรงรฃo. | Muita flexibilidade รฉ fornecida para resolver problemas complexos, uma vez que os mรฉtodos sรฃo descobertos durante o tempo de execuรงรฃo. |







