Curso de Extensão: Linguagem de Programação C++ (Básico)
Faculdade de Informática, PUCRS, Porto Alegre, RS
Coordenação: Isabel Harb Manssour
Instrutores: Eduardo Bezerra e Cristiane Woszezenki
Herança
A herança está relacionada às hierarquias e as relações entre os objetos. No dia a dia, quando se fala de herança se refere à transferência de propriedades de um pai aos seus filhos, ou seja, aquilo que é do pai passa a ser do filho.
É comum ainda o dito popular “saiu ao pai”, que significa que o filho tem as mesmas características do pai. De uma maneira geral as pessoas sabem que o filho saiu ao pai mas não é ele, ou seja não são a mesma pessoa. E que o filho apresenta determinadas características diferentes de seu pai.
Na análise orientada a objeto, herança é o mecanismo em que uma classe filha compartilha automaticamente todos os métodos e atributos de sua classe pai. A herança permite implementar classes descendentes com métodos e atributos que se diferenciam da classe pai.
Herança é a propriedade de podermos criar classes que se ampliam a partir de definições básicas. De classes mais simples e genéricas para classes mais complexas e específicas.
Exemplo:
- Um Pentium II tem todas as características do Pentium preservadas, mas acrescentou mais memória cache. A memória cache já existia mas foi ampliada.
- Uma placa mãe nova apresenta a interface USB, é uma novidade que antes não existia.
O conceito de herança permite a criação de uma classe derivada, ou seja, dada uma classe base, pode-se criar uma classe derivada que herda todos os atributos e métodos da classe base.
Protótipo para herança
class Base {
//Definição dos atributos e métodos da classe Base
};
class Derivada: public Base {
//Definição dos atributos e métodos da classe Derivada
};
Observe a linha, class Derivada: public Base
nesta linha, informa-se que a classe Derivada é herdeira da classe Base.
A palavra public, é o especificador de herança e define a forma como a classe Derivada pode acessar os atributos e métodos da classe Base. O termo public indica que queremos que as funções e variáveis public na classe Base permaneçam public na classe Derivada. Em lugar do termo public, poderíamos optar por private ou protected. Em qualquer desses casos todas as variáveis e funções públicas da classe base seriam convertidas para a classe derivada (veja Seção Especificador de Herança). O uso de public nesses casos é o padrão.
Exemplo de herança em C++
#include <iostream> //Classe Base class Veiculo{ private: int motor; int n_rodas; public: void setNRodas(int); int getNRodas(void); }; void Veiculo::setNRodas(int rodas){ n_rodas = rodas; } int Veiculo::getNRodas(void ){ return n_rodas; } //Primeira classe derivada class Caminhao: public Veiculo{ private: int carga; public: int getCarga(void); void setCarga(int); void mostra(void); }; void Caminhao::setCarga(int c){ carga = c; } int Caminhao::getCarga(void){ return carga; } void Caminhao::mostra(void){ cout << “Caminhão: n rodas = “ << getNRodas( ) << “carga = ” << getCarga( ); } //Segunda classe derivada class Automovel : public Veiculo{ private: string tipo; public: void setTipo(string); string getTipo(void); void mostra(void); }; void Automóvel::setTipo(string t){ tipo = t; } void Automóvel::getTipo(void){ return tipo; } void Automóvel::mostra(void){ cout << “Automovel: n rodas = “ << getNRodas( ) << “tipo = ” << getTipo( ); } int main( ){ Caminhao FNM; Automóvel Fusca; FNM.setNRodas(12); FNM.setCarga(3000); FNM.mostra( ); Fusca.setNRodas(4); Fusca.setTipo(SEDAN); Fusca.mostra( ); return 0; }
ESPECIFICADOR DE HERANÇA
O especificador de herança altera a forma como se processa a herança. Pode-se usar os especificadores public, protect e private.
Protótipo:
class Derivada: public Base {};
class Derivada: protected Base {};
class Derivada: private Base {};
O acesso aos membros da classe Base vai depender do especificador de herança (public, protect e private) e dos especificadores de acesso na classe pai (public, protect e private). A tabela mostra o acesso herdado. Na primeira coluna o especificador de acesso utilizado na classe base, na segunda coluna o especificador de herança e na terceira coluna o acesso efetivamente herdado.
Observe na primeira linha da tabela, que se o atributo é public e o especificador de herança é public, o acesso herdado é public. Se o atributo é protected e o especificador de herança é private, o acesso herdado é private.
Tipo de acesso na classe base |
Especificador de herança |
Acesso herdado |
public |
public |
public |
protected |
public |
protected |
private |
public |
inacessível |
public |
protected |
protected |
protected |
protected |
protected |
private |
protected |
inacessível |
public |
private |
private |
protected |
private |
private |
private |
private |
inacessível |
Vamos esclarecer o uso do especificador de acesso em heranças através de um exemplo:
class A {
public:
int x;
protected:
int y;
private:
int z;
};
class B: public A {
int X() {return x;}; //ok x é público
int Y() {return y;}; //ok y é protegido
int Z() {return z;}; //Erro não tem acesso a z
};
class C: private A {
int X() {return x;}; //ok x é privado
int Y() {return y;}; //ok y é privado
int Z() {return z;}; //Erro não tem acesso a z
};