Prévia do material em texto
LINGUAGEM DE PROGRAMAÇÃO Priscila de Fátima Gonçalves Introdução à herança em C++ Objetivos de aprendizagem Ao final deste texto, você deve apresentar os seguintes aprendizados: � Definir o que é herança em orientação a objetos. � Identificar a necessidade da criação de uma estrutura de herança. � Construir estruturas de herança em uma linguagem de programação. Introdução Ao estudar herança, você percebe seus conceitos, aprende a realizar reutilização de código (poupando tempo de desenvolvimento), como utilizar construtores e funções-membro da classe base, bem como a diferença entre vinculação estática e dinâmica. Neste capítulo, você estudará um importante conceito de progra- mação orientada a objetos. Por meio da utilização da herança você será capaz de definir classes novas que serão extensões de classes existentes. Conceito A herança é um dos principais pontos da programação orientada a objetos, promovendo a extensibilidade do código, a reutilização e uma maior coerência lógica no modelo de implementação. Os métodos herdados são usados da mesma forma que os métodos não herdados, nenhum trecho de código é ne- cessário para mencionar que os métodos serão herdados, o uso do recurso em uma classe não requer saber se ele foi ou não herdado, o que gera flexibilidade para o programador. Entre as vantagens oferecidas pela herança, podemos citar a manutenção de bibliotecas, para uso futuro de determinados recursos que sejam utilizados com frequência. Segundo Horstmann (2005), a herança é um mecanismo para melhorar classes existentes, ou seja, se uma classe nova precisa ser implementada e há uma classe com um conceito geral já disponível, a nova classe poderá herdar da classe existente. Em C++, uma classe ou estrutura pode ter mais de uma classe base direta ou estrutura, permitindo especificar se você deseja que uma classe seja uma classe base simples ou uma classe base virtual. Veja exemplos nas Figuras 1 e 2. Figura 1. Definição de classe derivada que apresenta o relacionamento entre as classes. Fonte: Horstmann (2005, p. 386). Figura 2. Diagrama de herança que apresenta o relacionamento entre as classes. Fonte: Horstmann (2005, p. 387). Introdução à herança em C++160 Necessidade da criação de uma estrutura de herança Os dados-membro de uma classe base estão presentes em cada objeto de uma classe derivada. Porém, não podem ser acessados pelas funções-membro dessa classe. Como se tratam de dados privativos da classe base, somente ela tem acesso a eles. Isto mostra que a classe derivada não tem mais direitos de acesso do que qualquer outra classe. Quando uma classe é instanciada, o construtor é chamado. Dessa forma, se ela for derivada de outra, o construtor da classe base é chamado antes. Ainda dentro desse contexto, se a classe base for derivada de outra, o processo se repetirá de forma recursiva, até que uma classe não derivada seja atingida, o que se torna essencial para manter a compatibilidade para o objeto criado. Quando uma classe base não possuir um construtor sem parâmetros, a classe derivada tem que declarar um construtor, mesmo que ele esteja vazio. O construtor de uma classe derivada tem duas funções: a primeira refere-se a inicializar o objeto base; e a segunda, a inicializar todos os dados-membro. Observe o modelo da Figura 3. Figura 3. Construtor com inicializador de classe base. Fonte: Horstmann (2005, p. 392). 161Introdução à herança em C++ Caso seja omitido o construtor de uma classe base, o objeto base será construído com o construtor default dela. Porém, se a classe base não possuir um construtor default, você terá que chamar, de forma explícita, um construtor da classe base no construtor da classe derivada. Se você invocar outra função- -membro sobre o parâmetro implícito, não precisará especificar o parâmetro, mas somente escrever o nome da função-membro. Segundo Horstmann (2005), um dos erros mais frequentes é tentar acessar campos privativos da classe base. Outro possível erro é que, ao estender a funcionalidade de uma função da classe base, os programadores se esquecem do nome da classe. Assim, sempre que se chama uma função de determinada classe base a partir de uma função do mesmo nome de uma classe derivada, tenha a certeza de fornecer o nome completo da função, incluindo o nome da classe base. Ainda dentro da implementação de herança, você precisa saber que existem tipos de vinculação de objetos, dinâmica e estática. O tipo estático é o tipo foi declarado no texto do programa como tipo ponteiro, sem fazer qualquer diferença para onde está apontando; já o tipo dinâmico é determinado pelo tipo de objeto ao qual se refere neste momento, sendo assim, indica como ele se comportará. O tipo dinâmico pode ser modificado à medida que o programa for sendo executado, normalmente por meio de atribuições. As funções virtuais são dinamicamente vinculadas, portanto, a função espe- cífica chamada será determinada pelo tipo dinâmico de objeto, de acordo com o modo como é chamada. Porém, os parâmetros são vinculados estaticamente, ou seja, você pode chamar uma função definida em uma classe derivada, mas deve utilizar um valor padrão de parâmetro da classe base. Nunca redefina um valor padrão de parâmetros herdados, porque os valores padrão herdados são estaticamente vinculados, enquanto as funções virtu- ais – as únicas funções que você deve sobrescrever – são dinamicamente vinculadas (MEYERS, 2011, p. 203). “Uma classe derivada herda todos os campos de uma classe base. Porém, se os campos forem privativos, as funções da classe derivada não possuem direito de acesso a eles” (HORSTMANN, 2005, p. 396). Introdução à herança em C++162 Construção de estruturas de herança em uma linguagem de programação Quando uma classe herda da outra, membros da classe base são incorporados como membros da classe derivada. Como as restrições de acessos são geren- ciadas em classes diferentes, principalmente o acesso aos membros da classe base a partir das derivadas, você deve aplicar os especificadores de acesso para obter o controle de acesso à classe base, são eles: � public; � private; � protected. Herança pública garante que tudo o que se aplica a objetos da classe base, será aplicado aos objetos da classe derivada, porque cada objeto da classe derivada é um objeto da classe base. Na classe herdada como public, membros da classe derivada permanecem como públicos; membros private da classe base só podem ser acessados por meio de funções públicas ou protegidas da classe base; e membros protected que estiverem na classe derivada se comportam na classe derivada como protegidos. A utilização do atributo protected funciona da mesma forma que o private sob o ponto de vista interno da classe, a diferença está no fato de que atributos protected são visíveis pelas classes derivadas, ao passo que os private não. Essas características podem ser traduzidas por permitir flexibilidade para o programador. Na classe herdada como protected, membros public da classe base ficam como se estivessem protegidos na classe derivada; membros private só podem ser acessados por funções da classe base que se utilizem das informações que estão neles; e membros protected se comportam como se fossem copiados como protegidos na classe derivada. Na classe herdada como private, membros public agem como se fossem private na classe derivada, membros private estarão presentes, porém ocultos como private, só podendo ser acessados por funções da classe base que se utili- zem das informações que neles contém; já os membros protected comportam-se como private na classe derivada. Assim, sobressai o atributo mais restritivo. 163Introdução à herança em C++ Em C++ pode ocorrer de uma classe derivada herdar membros de várias classes base, o que poderá dar ao programador, maior poder de modelagem, porém necessitará de mais cuidado na sua utilização, em razão do que chama- mos de heranças múltiplas. Observe no Quadro 1 umarelação entre heranças e seus acessos permitidos. Fonte: Adaptado de Aguilar (2008, p. 623). Tipo de herança Acesso a membro classe base Acesso a membro classe derivada Privado Privado Protegido Público Inacessível Privado Privado Protegido Privado Protegido Público Inacessível Protegido Protegido Público Público Protegido Público Público Protegido Público (Omitido) Público Protegido Público Público Protegido Público Quadro 1. Tipos de herança considerados no pseudocódigo e acessos permitidos Introdução à herança em C++164 Observe a demonstração de herança a seguir. 165Introdução à herança em C++ Introdução à herança em C++166 167Introdução à herança em C++ AGUILAR, L. J. Fundamentos de programação: algoritmos, estruturas de dados e objetos. Porto Alegre: McGraw-Hill, 2008. HORSTMANN, C. Conceitos de computação com o essencial de C++. 3. ed. Porto Alegre: Bookman, 2005. MEYERS, S. C ++ eficaz: 55 maneiras de aprimorar seus programas e projetos. 3. ed. Porto Alegre: Bookman, 2011. Leituras recomendadas VOTRE, V. P. C++ explicado e aplicado. Rio de Janeiro: Alta Books, 2016. WIKILIVROS. Programar em C++: herança. 2011. Disponível em: <https://pt.wikibooks. org/wiki/Programar_em_C%2B%2B/Heran%C3%A7a>. Acesso em: 23 abr. 2018.