Prefácio
O título "O problema de reduzir a acessibilidade das subclasses sobre as funções da classe dos pais em Java e C ++" parece ser mais acadêmico, mas é realmente um problema fácil de ignorar. Este artigo se esforça para elaborar a diferença entre esse problema em Java e C ++.
Primeiro, apresentaremos o que é "redução de acessibilidade das subclasses sobre a cobertura da função da classe pai". Para herança, as subclasses podem substituir as "funções virtuais" da classe pai - embora não haja funções virtuais a termo em Java, todas as funções Java podem ser consideradas funções virtuais, porque todas as funções Java podem ser substituídas por subclasses. Aqui, emprestamos apenas o significado do termo "função virtual" e não investigamos os detalhes do idioma. Java e C ++ permitem alterar a acessibilidade das funções ao substituir. A chamada "acessibilidade" é usar caracteres de controle de acesso, como público, protegido e privado, para modificá-lo para controlar se a função pode ser acessada. Normalmente, a ordem de acessibilidade é (como não há conceito de pacotes em C ++, o controle de acesso à embalagem não é considerado por enquanto, o que não afeta a discussão aqui):
público> protegido> privado
Tome Java como exemplo:
classe Base {Protected void SayHello () {System.out.println ("Hello in Base"); }} classe Child estende a base {public void SayHello () {System.out.println ("Hello in Child"); }} Nota: a função sayHello() aqui. Na base da classe pai, essa função é modificada usando o caractere de controle de acesso protegido. E as subclasses usam o público, em vez disso, não haverá problema. Quando as subclasses substituem as funções da classe pai, a expansão da acessibilidade geralmente não é um problema.
Java e C ++ adotam estratégias diferentes quando as subclasses reduzem a substituição da acessibilidade às funções da classe dos pais.
Primeiro, tome Java como exemplo e veja o código a seguir:
classe base {public void dizhello () {System.out.println ("Hello in Base"); }} classe Child estende a base {private void SayHello () {System.out.println ("Hello in Child"); }}No código acima, haverá um erro de compilação na linha 8 destacada - esse código não pode ser compilado! O Java não permite que as subclasses reduzam a acessibilidade ao substituir as funções da classe pai. Quanto aos motivos, podemos usar um exemplo para ilustrar. Por exemplo, escrevemos o seguinte código fora da classe:
Base base = new base (); base.sayhello (); base = new Child (); base.sayhello ();
Se o código anterior puder ser compilado, existe a possibilidade de que, quando a base apontar para New Base (), Sayhello () possa ser acessado, mas quando a base apontar para o novo filho (), Sayhello () não poderá ser acessado! Na visão de Java, isso é uma contradição, e esse problema deve ser evitado. Portanto, Java estipula da perspectiva do compilador de que não podemos escrever o código acima.
Para C ++, a situação é diferente. Vamos dar uma olhada no exemplo C ++:
classe base {public: virtual void dizhello () {std :: cout << "hello in base"; }} classe Child: Public Base {Private: void SayHello () {std :: cout << "Hello in Child"; }}Este código está completamente correto em C ++. Observe que a subclasse aqui reduz a acessibilidade ao substituir as funções da classe pai. Se você não vir nenhum problema, podemos escrever o seguinte código fora da classe:
Criança criança; criança.sayhello (); // não pode ser compilado porque diz quehello () é o static_cast <base &> (criança) .sayhello (); // não pode ser compilado porque diz quehello () é público
A chamada da linha 2 falha porque na criança, sayHello() é privada e não pode ser chamada externamente. No entanto, quando lançamos a criança para basear o objeto usando static_cast, as coisas mudam - para a base, sayHello() é público, para que possa ser chamado normalmente.
Para esse fim, o exemplo a seguir pode ser encontrado na seção Acesso às funções virtuais do capítulo de controle de acesso ao membro padrão C ++:
classe b {public: virtual int f ();}; classe d: public b {private: int f ();}; void f () {d d; B* pb = & d; D* pd = & d; pb-> f (); // ok: b :: f () é público, d :: f () é invocado pd-> f (); // erro: d :: f () é privado}Nesse sentido, o padrão C ++ fornece uma explicação:
O acesso é verificado no ponto de chamada usando o tipo de expressão usada para denotar o objeto para o qual a função do membro é chamada (b* no exemplo acima). O acesso da função do membro na classe em que foi definido (D no exemplo acima) é em geral não conhecido.
Existem dois pontos -chave para uma tradução simples:
Por esse motivo, os chamadores de C ++ parecem ser capazes de "inteligentemente" chamar funções que eram originalmente inacessíveis através de algumas transformações hábeis. Um exemplo mais prático é: no qt, QObject::event() é pública e sua função Subclasse Qwidget event() é alterada para protegida. Para detalhes, você pode ler o código relevante do QT.
Em resumo, quando as subclasses substituem as funções dos pais, Java limita estritamente que as subclasses não podem restringir a acessibilidade da função, mas o C ++ não tem essa limitação. Pessoalmente, acredito que, da perspectiva da engenharia de software, os regulamentos Java, sem dúvida, têm mais significado de engenharia, e as chamadas das funções são mais consistentes. O padrão C ++ simplificará significativamente a implementação do compilador, mas não é uma boa referência para a engenharia.
PS: A versão oficial do padrão C ++ requer compra, mas o rascunho pode ser baixado gratuitamente. O endereço de download do rascunho padrão do C ++ pode ser encontrado na página seguinte: https://isocpp.org/std/the-tandard
Resumir
O acima é o conteúdo inteiro deste artigo. Espero que o conteúdo deste artigo tenha certo valor de referência para o estudo ou trabalho de todos. Se você tiver alguma dúvida, pode deixar uma mensagem para se comunicar. Obrigado pelo seu apoio ao wulin.com.