Pergunta

Alguém está ciente de um recurso ou técnica de linguagem em C++ para evitar que uma classe filha exagere em um método específico na classe pai?

class Base {
public:
    bool someGuaranteedResult() { return true; }
};

class Child : public Base {
public:
    bool someGuaranteedResult() { return false; /* Haha I broke things! */ }
};

Mesmo que não seja virtual, isso ainda é permitido (pelo menos no compilador Metrowerks que estou usando), tudo o que você recebe é um aviso em tempo de compilação sobre como ocultar a função X herdada não virtual.

Foi útil?

Solução

Algumas ideias:

  1. Torne sua função privada.
  2. Não torne sua função virtual.Na verdade, isso não impede que a função seja ofuscada por outra definição.

Fora isso, não conheço um recurso de linguagem que bloqueie sua função de forma a evitar que ela seja sobrecarregada e ainda possa ser invocada por meio de um ponteiro/referência à classe filha.

Boa sorte!

Outras dicas

Quando você pode usar o final especificador para métodos virtuais (introduzido no C++ 11), você pode fazer isso.Deixe-me citar meu site de documentos favorito:

Quando usado em uma declaração de função virtual, final especifica que a função não pode ser substituída por classes derivadas.

Adaptado ao seu exemplo seria assim:

class Base {
public:
    virtual bool someGuaranteedResult() final { return true; }
};

class Child : public Base {
public:
    bool someGuaranteedResult() { return false; /* Haha I broke things! */ }
};

Quando compilado:

$ g++ test.cc -std=c++11
test.cc:8:10: error: virtual function ‘virtual bool Child::someGuaranteedResult()’
test.cc:3:18: error: overriding final function ‘virtual bool Base::someGuaranteedResult()’

Quando você estiver trabalhando com um compilador Microsoft, dê uma olhada também no sealed palavra-chave.

Parece que o que você está procurando é equivalente à linguagem Java final palavra-chave que impede que um método seja substituído por uma subclasse.

Como outros aqui tem sugerido, você realmente não pode evitar isso.Além disso, parece que este é um assunto bastante pergunta frequente.

(a) Não acho que tornar a função privada seja a solução porque isso apenas ocultará a função da classe base da classe derivada. A classe derivada sempre pode definir uma nova função com a mesma assinatura.(b) Tornar a função não virtual também não é uma solução completa porque, se a classe derivada redefinir a mesma função, pode-se sempre chamar a função da classe derivada por ligação em tempo de compilação, ou seja, obj.someFunction() onde obj é uma instância do classe derivada.

Não acho que haja uma maneira de fazer isso. Além disso, gostaria de saber o motivo de sua decisão de proibir classes derivadas de substituir funções de classe base.

Para esclarecimento, a maioria de vocês entendeu mal a pergunta dele.Ele não está perguntando sobre "substituir" um método, ele está perguntando se existe uma maneira de evitar a "ocultação" ou não.E a resposta simples é que “não existe!”.

Aqui está o exemplo dele mais uma vez

A classe pai define uma função:

int foo() { return 1; }

Classe filha, herdando o Pai define a mesma função NOVAMENTE (não substituindo):

int foo() { return 2; }

Você pode fazer isso em todas as linguagens de programação.Não há nada que impeça a compilação deste código (exceto uma configuração no compilador).O melhor que você receberá é um aviso de que está ocultando o método dos pais.Se você chamar a classe filha e invocar o método foo, obterá 2.Você praticamente quebrou o código.

Isto é o que ele está perguntando.

um aviso em tempo de compilação sobre a ocultação da função X herdada não virtual.

altere as configurações do compilador para gerar um erro em vez de um aviso.

Acho que o que o compilador avisa está se escondendo !!Está realmente sendo substituído?

O compilador pode fornecer um aviso, mas em tempo de execução, o método da classe pai será chamado se o ponteiro for do tipo classe pai, independentemente do tipo real do objeto para o qual ele aponta.

Isto é interessante.Tente criar um pequeno programa de teste independente para o seu compilador.

Eu estava procurando o mesmo e ontem cheguei a essa pergunta [bastante antiga].

Hoje encontrei uma palavra-chave c++11 bacana: final .Achei que pode ser útil para próximos leitores.

http://en.cppreference.com/w/cpp/idioma/final

Se você abordar a classe filha como um tipo de pai, uma função não virtual chamará a versão da classe pai.

ou seja:

Parent* obj = new Child();

A menos que você torne o método virtual, a classe filha não poderá substituí-lo.Se você quiser evitar que classes filhas o chamem, torne-o privado.

Então, por padrão, o C++ faz o que você deseja.

Tentar impedir que alguém use o mesmo nome de sua função em uma subclasse não é muito diferente de tentar impedir que alguém use o mesmo nome de função global que você declarou em uma biblioteca vinculada.

Você só pode esperar que os usuários que pretendem usar seu código, e não o de outros, tenham cuidado com a forma como fazem referência ao seu código e que usem o tipo de ponteiro correto ou um escopo totalmente qualificado.

No seu exemplo, nenhuma função é substituída.Em vez disso, está oculto (é uma espécie de caso degenerado de sobrecarga).O erro está no código da classe Child.Como sugerido pelo csmba, tudo o que você pode fazer é alterar as configurações do compilador (se possível);tudo bem, desde que você não use uma biblioteca de terceiros que oculte suas próprias funções.

Tecnicamente, você pode impedir que funções virtuais sejam substituídas.Mas você nunca será capaz de alterar ou adicionar mais.Isso não é ajuda completa.Melhor usar o comentário na frente da função, como sugere o faq lite.

Os métodos C++ são privados e não substituíveis por padrão.

  • Você não pode substituir um método privado
  • Você não pode substituir um não-virtual método

Você está se referindo à sobrecarga?

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top