Para responder a essa pergunta, gostaria de descrever os acessadores dos membros primeiro com minhas próprias palavras. Se você já sabe disso, pule para o título "próximo:".
Há três assessores que eu estou ciente de: public
, protected
e private
.
Deixei:
class Base {
public:
int publicMember;
protected:
int protectedMember;
private:
int privateMember;
};
- Tudo o que está ciente
Base
também está ciente de que Base
contém publicMember
.
- Somente as crianças (e seus filhos) estão cientes de que
Base
contém protectedMember
.
- Ninguém, mas
Base
está ciente privateMember
.
Por "está ciente de", quero dizer "reconheça a existência e, portanto, seja capaz de acessar".
Próximo:
O mesmo acontece com a herança pública, privada e protegida. Vamos considerar uma classe Base
e uma classe Child
que herda Base
.
- Se a herança é
public
, tudo o que está ciente Base
e Child
também está ciente que Child
herda Base
.
- Se a herança é
protected
apenas Child
, e seus filhos, estão cientes de que eles herdam Base
.
- Se a herança é
private
, ninguém além disso Child
está ciente da herança.
SomeBase
é como uma maneira codificada de compor em um membro anônimo do tipoSomeBase
. Este, como qualquer outro membro, possui um especificador de acesso, que exerce o mesmo controle no acesso externo.NOTA IMPORTANTE: As classes B, C e D contêm todas as variáveis x, ye z. É apenas uma questão de acesso.
Sobre o uso da herança protegida e privada, você pode ler aqui .
fonte
Limitar a visibilidade da herança tornará o código incapaz de ver que alguma classe herda outra classe: conversões implícitas da derivada para a base não funcionarão e
static_cast
da base para a derivada também não funcionará.Somente membros / amigos de uma classe podem ver herança privada, e somente membros / amigos e classes derivadas podem ver herança protegida.
herança pública
Herança IS-A. Um botão é uma janela e, em qualquer lugar em que uma janela seja necessária, também pode ser passado um botão.
herança protegida
Implementado protegido em termos de. Raramente útil. Usado
boost::compressed_pair
para derivar de classes vazias e economizar memória usando a otimização de classe base vazia (o exemplo abaixo não usa modelo para continuar sendo o ponto):herança privada
Implementado em termos de. O uso da classe base é apenas para implementar a classe derivada. Útil com características e se o tamanho importa (características vazias que contêm apenas funções farão uso da otimização da classe base vazia). Muitas vezes , porém, a contenção é a melhor solução. O tamanho das strings é crítico, por isso é um uso frequentemente visto aqui
membro público
Agregar
Accessors
membro protegido
Fornecendo acesso aprimorado para classes derivadas
membro privado
Manter detalhes da implementação
Observe que as projeções no estilo C permitem propositalmente converter uma classe derivada para uma classe base protegida ou privada de uma maneira definida e segura e também para a outra direção. Isso deve ser evitado a todo custo, porque pode tornar o código dependente dos detalhes da implementação - mas, se necessário, você pode fazer uso dessa técnica.
fonte
Essas três palavras-chave também são usadas em um contexto completamente diferente para especificar o modelo de herança de visibilidade .
Esta tabela reúne todas as combinações possíveis do modelo de herança e declaração de componentes, apresentando o acesso resultante aos componentes quando a subclasse é completamente definida.
A tabela acima é interpretada da seguinte maneira (veja a primeira linha):
Um exemplo:
O acesso resultando em variáveis
p
,q
,r
na classe subsub é nenhum .O acesso resultante para variáveis
y
,z
na classe Sub, é protegido e para a variávelx
é none .Agora vamos definir uma subclasse:
A classe definida denominada Sub, que é uma subclasse da classe denominada
Super
ou essaSub
classe é derivada daSuper
classe. ASub
classe não apresenta novas variáveis nem novas funções. Isso significa que qualquer objeto daSub
classe herda todas as características após aSuper
classe ser de fato uma cópia de umSuper
objetos classe?Não . Não faz.
Se compilarmos o código a seguir, não obteremos nada além de erros de compilação dizendo que
put
eget
métodos são inacessíveis. Por quê?Quando omitimos o especificador de visibilidade, o compilador supõe que vamos aplicar a chamada herança privada . Isso significa que todos os componentes públicos da superclasse se tornam privados o acesso, os componentes da superclasse privadas não será acessível a todos. Consequentemente, significa que você não tem permissão para usá-lo dentro da subclasse.
Temos que informar ao compilador que queremos preservar a política de acesso usada anteriormente.
Objetos da
Sub
classe podem fazer "quase" as mesmas coisas que seus irmãos mais velhos criados a partir daSuper
classe. "Quase" porque o fato de ser uma subclasse também significa que a classe perdeu o acesso aos componentes privados da superclasse . Não podemos escrever uma função membro daSub
classe que seria capaz de manipular diretamente a variável de armazenamento.Esta é uma restrição muito séria. Existe alguma solução alternativa?
Sim .
O terceiro nível de acesso é chamado de protegido . A palavra-chave protegida significa que o componente marcado com ela comporta como um público quando usado por qualquer uma das subclasses e se parece com um privado para o resto do mundo . - Isso é verdade apenas para as classes herdadas público (como a classe Super no nosso exemplo) -
Como você pode ver no código de exemplo, temos uma nova funcionalidade para a
Sub
classe e ela faz uma coisa importante: acessa a variável de armazenamento da classe Super .Não seria possível se a variável fosse declarada como privada. No escopo da função principal, a variável permanece oculta mesmo assim, se você escrever algo como:
O compilador irá informá-lo que é um
error: 'int Super::storage' is protected
.Por fim, o último programa produzirá a seguinte saída:
fonte
Tem a ver com a maneira como os membros públicos da classe base são expostos a partir da classe derivada.
Como o litb aponta, a herança pública é uma herança tradicional que você verá na maioria das linguagens de programação. É isso que modela um relacionamento "IS-A". A herança privada, algo que o AFAIK peculiar ao C ++, é um relacionamento "IMPLEMENTADO EM TERMOS DE". Ou seja, você deseja usar a interface pública na classe derivada, mas não deseja que o usuário da classe derivada tenha acesso a essa interface. Muitos argumentam que, nesse caso, você deve agregar a classe base, ou seja, em vez de ter a classe base como uma base privada, crie um membro derivado para reutilizar a funcionalidade da classe base.
fonte
Tipo de herança : Objeto herdado como :
fonte
1) Herança Pública :
uma. Membros privados da classe Base não estão acessíveis na classe Derivada.
b. Membros protegidos da classe Base permanecem protegidos na classe Derived.
c. Os membros públicos da classe Base permanecem públicos na classe Derived.
Portanto, outras classes podem usar membros públicos da classe Base por meio do objeto de classe Derived.
2) Herança Protegida :
uma. Membros privados da classe Base não estão acessíveis na classe Derivada.
b. Membros protegidos da classe Base permanecem protegidos na classe Derived.
c. Os membros públicos da classe Base também se tornam membros protegidos da classe Derived.
Portanto, outras classes não podem usar membros públicos da classe Base através do objeto de classe Derived; mas eles estão disponíveis para a subclasse de Derivado.
3) Herança Privada :
uma. Membros privados da classe Base não estão acessíveis na classe Derivada.
b. Membros protegidos e públicos da classe Base tornam-se membros privados da classe Derived.
Portanto, nenhum membro da classe Base pode ser acessado por outras classes por meio do objeto de classe Derived, pois são particulares na classe Derived. Portanto, mesmo a subclasse da classe Derived não pode acessá-los.
fonte
A herança pública modela um relacionamento IS-A. Com
tudo
D
é umB
.A herança privada modela um relacionamento IS-IMPLEMENTED-USING (ou o que for chamado). Com
a não
D
é a , mas todos os usam em sua implementação. A herança privada sempre pode ser eliminada usando a contenção:B
D
B
Isso
D
também pode ser implementado usandoB
, neste caso, usando seub_
. A contenção é um acoplamento menos rígido entre os tipos do que a herança, portanto, em geral, deve ser preferido. Às vezes, usar a contenção em vez da herança privada não é tão conveniente quanto a herança privada. Muitas vezes isso é uma desculpa esfarrapada por ser preguiçoso.Acho que ninguém sabe que
protected
modelos de herança. Pelo menos ainda não vi nenhuma explicação convincente.fonte
D
deriva de maneira particularD
, ele pode substituir as funções virtuais doB
. (Se, por exemplo,B
for uma interface de observador, éD
possível implementá-la e passarthis
para funções que exigem essa interface, sem que todos possam usarD
como observador.) Além disso, tambémD
poderia disponibilizar membros de maneira seletivaB
em sua interfaceusing B::member
. Ambos são sintaticamente inconvenientes para implementar quandoB
é um membro.protected
herança que eu encontrei útil com umavirtual
classe base eprotected
ctor:struct CommonStuff { CommonStuff(Stuff*) {/* assert !=0 */ } }; struct HandlerMixin1 : protected virtual CommonStuff { protected: HandlerMixin1() : CommonStuff(nullptr) {} /*...*/ }; struct Handler : HandlerMixin1, ... { Handler(Stuff& stuff) : CommonStuff(&stuff) {} };
Se você herdar publicamente de outra classe, todos saberão que você está herdando e você poderá ser usado polimorficamente por qualquer pessoa através de um ponteiro de classe base.
Se você herdar de forma protegida, apenas as classes de seus filhos poderão usá-lo polimorficamente.
Se você herdar privadamente, somente você poderá executar os métodos da classe pai.
O que basicamente simboliza o conhecimento que o restante das classes tem sobre o seu relacionamento com a classe dos pais
fonte
Os membros de dados protegidos podem ser acessados por quaisquer classes herdadas da sua classe. Membros de dados privados, no entanto, não podem. Digamos que temos o seguinte:
De dentro da sua extensão para esta classe, a referência
this.myPrivateMember
não funcionará. No entanto,this.myProtectedMember
vontade. O valor ainda está encapsulado, portanto, se tivermos uma instanciação dessa classe chamadamyObj
,myObj.myProtectedMember
não funcionará, portanto, é semelhante em função a um membro de dados privado.fonte
Baseado neste exemplo para java ... acho que uma mesinha vale mais que mil palavras :)
fonte
Resumo:
Ao herdar, você pode (em alguns idiomas) alterar o tipo de proteção de um membro de dados em determinada direção, por exemplo, de protegido para público.
fonte
Privado:
Os membros privados de uma classe base só podem ser acessados por membros dessa classe base.
Público:
Os membros públicos de uma classe base podem ser acessados por membros dessa classe base, membros de sua classe derivada, bem como membros que estão fora da classe base e da classe derivada.
Protegido:
Os membros protegidos de uma classe base podem ser acessados por membros da classe base e por membros de sua classe derivada.
Em resumo:
privado : base
protegido : base + derivado
público : base + derivado + qualquer outro membro
fonte
Encontrei uma resposta fácil e pensei em publicá-la para minha referência futura também.
É dos links http://www.learncpp.com/cpp-tutorial/115-inheritance-and-access-specifiers/
fonte
É essencialmente a proteção de acesso dos membros públicos e protegidos da classe base na classe derivada. Com a herança pública, a classe derivada pode ver membros públicos e protegidos da base. Com herança privada, não pode. Com protected, a classe derivada e quaisquer classes derivadas disso podem vê-los.
fonte