Funções Virtuais
Por Natã Melo
(nata.venancio.melo@gmail.com)
Entenda pra que serve e como funcionam as funções virtuais na Linguagem C++.

Inicialmente chamada de C with Classes, C++ é uma linguagem de programação multi-paradigma que foi desenvolvida como um adicional à linguagem C. Dentre os paradigmas englobados por C++, estão: Paradigma Orientado a Objeto e o Paradigma Imperativo. Classes, sobrecarga de operadores, herança múltipla, gabaritos e tratamento de exceções são algumas características suportadas por C++.

Contudo, existe um recurso de C++ que, do ponto vista de Orientação a Objeto, é o mais importante da linguagem: são as funções virtuais. Para que uma função seja virtual, basta declará-la como virtual, ou seja, acrescenta-se no início da declaração do método a palavra virtual.

Uma função declarada como virtual, numa classe (base), pode ser reimplementada pelas classes derivadas, sobrepondo, dessa forma, a definição da função na classe base. Se acessada normalmente, uma função virtual se comporta como uma função comum, membro da classe. Entretanto, quando acessada por meio de ponteiros, o comportamento não é o similar ao de uma função comum.

Ao apontar para um objeto derivado com uma função virtual, C++ determina qual versão executar baseada no conteúdo do apontador. Logo, quando os apontadores referenciarem diferentes objetos, versões diferentes da função virtual serão executadas.

Considere o exemplo a seguir.

#include 
using namespace std;
class PosComp1 {
	public:
		virtual void Calcula(void)
		{ cout << "1"; };
};
class PosComp2 : public PosComp1 {
	public:
		void Calcula(void)
		{ cout << "2"; }
};

Se essas classes forem executadas a partir do programa:

main() { 
	PosComp1 *p, po; 
	PosComp2 p2; 
	// Ponteiro p de PosComp1 apontando para PosComp1.
	p = &po; 
	p -> Calcula();

	// Ponteiro p de PosComp1 apontando para PosComp2.
	p = &p2;
	p -> Calcula();
	// Variável po (do tipo PosComp1) contendo PosComp2 
	// e convertida em PosComp1.
	po = p2;
	po.Calcula();
	return(0); 
}

O resultado da execução do código anterior será: 1 2 1. Perceba que a versão da função que será invocada (em "p -> Calcula()") só será obtida em tempo de execução, de acordo com o conteúdo do ponteiro "p" e não de acordo com o tipo do ponteiro. Isso acontece devido ao uso do recurso virtual.

No trecho "po = p2;", "po" está sendo definido com uma variável do tipo "PosComp2", dessa forma, "po" possui o conteúdo de "p2". Entretanto, "po" é convertido para o tipo "PosComp1". Por esse fato, quando o trecho "po.Calcula()" é executado, o valor da saída é 1 e não 2, como ocorre no último trecho "po.Calcula()", onde o acesso à função virtual por meio de ponteiros escolhe a versão de "Calcula()" implementada na classe "PosComp2".

O uso do recurso virtual em métodos se assemelha à sobrecarga de funções, porém, as redefinições por classes derivadas, usualmente são denominadas de sobreposição. Vale salientar, que o uso desse recurso indica uma possibilidade de sobreposição da função, mas não sua obrigatoriedade.

Mais informações sobre o assunto, podem ser encontradas em: Aglae e POOCPP .

Jornal PETNews - Edição: Caio Paes - Revisão: Janderson Jason e Joseana Fechine
Grupo PET Computação UFCG, 2011. All rights reserved.