C++ Polimorfismo com Exemplo
O que é polimorfismo em C++?
In C++, o polimorfismo faz com que uma função membro se comporte de maneira diferente com base no objeto que a chama/invoca. Polimorfismo é uma palavra grega que significa ter muitas formas. Ocorre quando você tem uma hierarquia de classes relacionadas 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.
Tipos de polimorfismo
C++ suporta dois tipos de polimorfismo:
- Polimorfismo em tempo de compilação e
- Polimorfismo de tempo de execução.
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:
Explicação do código:
- 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++ operador. Ele também muda como o operador funciona. Por exemplo, podemos definir o operador + para concatenar duas strings. Nós o conhecemos como o operador de adição para adicionar valores numéricos. Após nossa definição, quando colocado entre inteiros, ele os adicionará. Quando colocado entre strings, ele os 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:
Explicação do código:
- 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 público para marcar o construtor como público, o que significa que ele estará acessível mesmo de fora do 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().
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:
Explicação do código:
- 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:
Explicação do código:
- 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().
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 já que a descoberta dos métodos é feita durante o tempo de compilação | Execução mais lenta, pois o descobridor do método é feito durante o 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. |
Resumo
- Polimorfismo significa ter muitas formas.
- Ocorre quando existe uma hierarquia de classes relacionadas por herança.
- Com o polimorfismo, uma função pode se comportar de maneira diferente com base no objeto que a invoca/chama.
- No polimorfismo em tempo de compilação, a função a ser invocada é estabelecida durante o tempo de compilação.
- No polimorfismo de tempo de execução, a função a ser invocada é estabelecida durante o tempo de execução.
- O polimorfismo em tempo de compilação é determinado por sobrecarga de função e sobrecarga de operador.
- Na sobrecarga de funções, existem muitas funções com nomes semelhantes, mas argumentos diferentes.
- Os parâmetros podem diferir em número ou tipo.
- Na sobrecarga do operador, um novo significado é definido para C++ operadores.
- O polimorfismo de tempo de execução é obtido por meio da substituição de funções.
- Na substituição de função, uma classe derivada fornece uma nova definição para uma função definida na classe base.