Prévia do material em texto
LINGUAGEM DE PROGRAMAÇÃO Priscila Gonçalves Funções virtuais Objetivos de aprendizagem Ao final deste texto, você deve apresentar os seguintes aprendizados: � Conceituar funções virtuais em classes derivadas. � Reconhecer uma função virtual. � Implementar uma função virtual. Introdução Funções virtuais têm a finalidade de definir uma função vinculada di- namicamente, podendo ser redefinida em classes derivadas, ou seja, quando a função é chamada, o tipo do parâmetro implícito determina qual versão da função será executada. Neste capítulo, você estudará o conceito de funções virtuais, como reconhecê-las e de que maneira utilizá-las na programação. Você apren- derá, também, a utilizar funções virtuais apenas quando necessitar de flexibilidade da vinculação dinâmica durante a execução de um programa. Funções virtuais em classes derivadas A palavra virtual deve ser utilizada em uma classe base, ou seja, funções de mesmo nome e tipo de parâmetros, em classes derivadas, serão automati- camente virtuais. Conforme Horstmann (2005), quando você fizer referência a um objeto de classe derivada, utilizando um ponteiro ou uma referência à classe base, poderá chamar uma função virtual para esse objeto, e executará a versão da classe derivada da função. As funções virtuais irão assegurar que a função correta seja chamada para um objeto e, isso não depende da expressão utilizada para fazer a chamada de função. As funções virtuais permitem a personalização das implementações das classes derivadas. Quando uma função virtual é chamada, o compilador de- termina o tipo do parâmetro implícito naquela chamada durante a execução, conforme você pode observar no exemplo a seguir. Vale lembrar que é considerada uma boa prática de programação fornecer a palavra virtual para as funções de classes derivadas também. Entre as funções virtuais, você irá aprender que existem as virtuais puras e as virtuais simples. Entre os recursos mais proeminentes das funções vir- tuais puras, como você pode ver na Figura 1, é possível descrever como elas devem ser redeclaradas por qualquer classe concreta que as herdar, em geral sem definições em classes abstratas. Conforme afirmado por Meyers (2011), o propósito das funções virtuais puras é fazer as classes derivadas herdarem apenas a interface de uma função. Figura 1. Função virtual pura. Fonte: Meyers (2011, p. 182). Nas funções virtuais simples, as classes herdam a interface da função, e esse tipo de função fornece uma implementação que as classes derivadas possam sobrescrever. Segundo Meyers (2011), o propósito das funções virtuais Funções virtuais2 simples é fazer classes derivadas herdarem a interface de uma função, assim como a implementação padrão para todas, conforme exemplo da Figura 2. Figura 2. Função virtual simples. Fonte: Meyers (2011, p. 183). Utilização da função virtual Você deverá utilizar uma função virtual para obter o comportamento desejado das funções, independentemente do tipo de objeto que é usado (uma classe base ou derivada). Dessa forma, os objetos serão manipulados por ponteiros, e a função permanecerá virtual em todos os níveis inferiores da hierarquia. Classes abstratas em geral são usadas como classe base para funções virtuais puras, e não fornecem implementações. São definidas interfaces públicas comuns para várias classes em uma hierarquia, que podem conter uma ou mais funções virtuais puras do que as classes derivadas concretas devem sobrescrever. Segundo Meyers (2011), instanciar um objeto de uma classe abstrata causa erro de compilação. Sobrescrever uma função virtual pura em uma classe derivada para tentar instanciar objetos dessa classe é um erro de compilação. 3Funções virtuais Implementação de função virtual Para implementar uma função virtual é necessário que os objetos carreguem informações que possam ser utilizadas em tempo de execução, determinando quais as funções virtuais devem ser invocadas no objeto. Cada classe com funções virtuais possui um ponteiro de função chamada de tabela virtual ou virtual table (vtbl) associada à tabela de funções virtuais (vtable). Se uma classe contém a função virtual, os objetos desse tipo aumentarão de tamanho. Por exemplo, em uma arquitetura de 32 bits, eles irão de 64 bits até 96 bits (para os inteiros), pois o compilador monta a tabela e, a cada chamada o RunTime, procura nela o ponteiro específico. Assim, o tempo pode ser 12 vezes maior que o da chamada de uma função normal. C ++ suporta herança múltipla, isso significa que uma classe ou estrutura pode ter mais de uma classe base direta ou estrutura, e não possui um tipo de interface separado. Geralmente, a herança múltipla deve ser evitada, exceto como uma solução alternativa para a falta de uma interface separada. Considere que você tenha três grupos de funcionalidades, cada um con- sistindo em funções e dados. Então, considere que os grupos não têm relação um com o outro, mas não são mutuamente exclusivos. Você pode querer colocar cada grupo de funcionalidades em sua própria classe. Se você tem uma situação em que pretende criar uma classe precisando de dois desses grupos, ou até mesmo todos os três, pode simplesmente criar uma classe que herda de todos os três. C ++ permite que você especifique se deseja que uma classe seja uma classe base simples ou uma classe base virtual, basta colocar a palavra-chave virtual antes do nome da classe no especificador da classe base. Toda vez que uma classe possui uma ou mais funções virtuais, o compilador cria uma vtable. O programa em execução usará essa tabela para selecionar a implementação apropriada de função toda vez que uma função virtual de uma classe específica for chamada. Qualquer classe que tiver um ou mais ponteiros nulos em sua vtable, será uma classe abstrata. Ao especificar classes das quais outra classe deriva em C ++, você também deverá determinar um especificador de acesso. Funções virtuais4 Suponha que uma classe base contenha uma função declarada como virtual e que uma classe derivada defina a mesma função. A função a partir da classe derivada é chamada para objetos da classe derivada, mesmo seja chamada usando um ponteiro ou uma referência à classe base. Para o seu melhor entendimento, o exemplo a seguir mostra uma classe base que fornece uma implementação da função de PrintBalance e de duas classes derivadas de um exemplo sobre o tema estudado. 5Funções virtuais As chamadas para PrintBalance são idênticas, com exceção do objeto para o qual pAccount aponta. Como PrintBalance é virtual, a versão da função definida para cada objeto é chamada. A função PrintBalance nas classes derivadas CheckingAccount e SavingsAccount “substitui” a função na classe base Account. Se uma classe que não fornece uma implementação substituta da função PrintBalance for chamada, a implementação padrão da classe base Account será usada. As funções nas classes derivadas substituem as funções virtuais nas classes base apenas se o tipo for o mesmo. Uma função em uma classe derivada não pode ser diferente de uma função virtual em uma classe base apenas no tipo de retorno, a lista de argumentos também deve ser diferente. Ao chamar uma função usando ponteiros ou referências, as seguintes regras se aplicam: � uma chamada a uma função virtual é resolvida de acordo com o tipo subjacente de objeto para o qual ela é chamada; � uma chamada a uma função não virtual é resolvida de acordo com o tipo de ponteiro ou de referência. O exemplo a seguir mostra como as funções virtuais e não virtuais se comportam quando chamadas por ponteiros. Funções virtuais6 Assim, deverá apresentar como saída: Independentemente da função NameOf ser chamada por um ponteiro para Base ou um ponteiro para Derived, ela chama a função para Derived, porque NameOf é uma função virtual, e pBase e pDerived apontam para um objeto do tipo Derived. Suprimindo o mecanismo de chamada das funções virtuais para chamar PrintBalance naclasse base, teríamos a seguinte forma: 7Funções virtuais 1. Qual a finalidade das funções virtuais? a) Funções virtuais têm a finalidade de definir uma função vinculada dinamicamente. b) Funções virtuais têm a finalidade de impedir a personalização das implementações das classes derivadas. c) Funções virtuais têm a finalidade de definir uma função vinculada estaticamente. d) Funções virtuais têm a finalidade de tornar inflexível a vinculação dinâmica durante a execução de um programa. e) Funções nas classes derivadas têm a finalidade de tornar insubstituíveis as funções virtuais nas classes base apenas se o tipo for o mesmo. 2. Ao chamar uma função usando ponteiros ou referências, as seguintes regras se aplicam: a) uma chamada a uma função não virtual não é resolvida de acordo com o tipo de ponteiro ou de referência. b) uma chamada a uma função virtual é resolvida de acordo com o tipo subjacente de objeto para o qual ela é chamada. c) como as funções virtuais são chamadas apenas para objetos dos tipos classe, é possível declarar funções globais ou estáticas como virtuais. d) a lista de argumentos também deve ser igual. e) o mecanismo de chamada de funções virtuais não pode ser suprimido. 3. De que maneira você pode tornar um programa facilmente extensível? a) Definindo uma nova classe. b) Utilizando funções virtuais. c) A palavra virtual não deve ser utilizada em uma classe base. d) Utilizando funções com nomes e tipos de parâmetros diferentes em classes derivadas. e) Deixando de referenciar um objeto da classe derivada e utilizando um ponteiro ou uma referência à classe base. 4. O que ocorre quando uma função virtual é chamada? a) Os objetos desse tipo diminuirão de tamanho. Funções virtuais8 HORSTMANN, C. Conceitos de computação com o essencial de C++. 3. ed. Porto Alegre: Bookman, 2005. MEYERS, S. C++ eficaz. 3. ed. Porto Alegre: Bookman, 2011. Leituras recomendadas CAMPISTA, M. Linguagens de programação. [2011]. Disponível em: <https://www.gta. ufrj.br/~miguel/lingprog.2018.1.html>. Acesso em: 8 abr. 2018. FUNÇÕES virtuais. [2016]. Disponível em: <https://msdn.microsoft.com/pt-br/ library/0y01k918.aspx>. Acesso em: 6 abr. 2018. PEREIRA, S. L. Linguagem C++. São Paulo: FATEC, 1999. b) As classes deixam de herdar a interface da função, e esse tipo de função não fornece uma implementação do que as classes derivadas possam sobrescrever. c) O compilador determina o tipo do parâmetro implícito naquela chamada durante a execução. d) As funções virtuais permitem a ramificação das implementações das classes derivadas. e) As funções virtuais irão assegurar que a função correta seja chamada para um objeto, dependendo da expressão utilizada para fazer a chamada de função. 5. Quais os propósitos das funções virtuais puras e das funções virtuais simples? a) As funções virtuais puras fazem as classes derivadas herdarem interface de uma função e a implementação padrão; já as funções virtuais simples, somente herdam a interface da função. b) O propósito das funções virtuais puras é fazer as classes derivadas herdarem apenas a interface de uma função; já para as funções virtuais simples, o propósito é fazer as classes derivadas herdarem a interface de uma função, assim como a implementação padrão para todas. c) As funções virtuais puras devem ser redeclaradas pela classe concreta determinada que as herdar. d) As funções virtuais fornecem uma implementação que as classes derivadas não podem sobrescrever. e) As funções virtuais simples geralmente não têm definições em classes abstratas. 9Funções virtuais https://www.gta/ http://ufrj.br/~miguel/lingprog.2018.1.html https://msdn.microsoft.com/pt-br/ Encerra aqui o trecho do livro disponibilizado para esta Unidade de Aprendizagem. Na Biblioteca Virtual da Instituição, você encontra a obra na íntegra. Conteúdo: