Eu não sou um cara de C ++, mas sou forçado a pensar sobre isso. Por que a herança múltipla é possível em C ++, mas não em C #? (Eu sei do problema do diamante , mas não é isso que estou perguntando aqui). Como o C ++ resolve a ambiguidade de assinaturas de método idênticas herdadas de várias classes base? E por que o mesmo design não foi incorporado ao C #?
c#
c++
language-design
multiple-inheritance
Sandeep
fonte
fonte
Respostas:
Penso (sem ter uma referência rígida), que em Java eles queriam limitar a expressividade da linguagem para facilitar a aprendizagem e porque o código que usa herança múltipla costuma ser muito complexo para seu próprio bem. E como a herança múltipla completa é muito mais complicada de implementar, também simplificou muito a máquina virtual (herança múltipla interage especialmente mal com o coletor de lixo, porque requer manter os ponteiros no meio do objeto (no início da base) )
E, ao projetar o C #, acho que eles observaram o Java, viram que a herança múltipla completa realmente não foi perdida e optaram por manter as coisas simples também.
Isso não acontece . Há uma sintaxe para chamar explicitamente o método da classe base de base específica, mas não há como substituir apenas um dos métodos virtuais e, se você não substituir o método na subclasse, não será possível chamá-lo sem especificar a base classe.
Não há nada a incorporar.
Como Giorgio mencionou métodos de extensão de interface nos comentários, explicarei o que são mixins e como eles são implementados em vários idiomas.
As interfaces em Java e C # são limitadas apenas a métodos de declaração. Mas os métodos precisam ser implementados em cada classe que herda a interface. No entanto, existe uma grande classe de interfaces, na qual seria útil fornecer implementações padrão de alguns métodos em termos de outros. Exemplo comum é comparável (em pseudo-idioma):
A diferença da classe completa é que isso não pode conter nenhum membro de dados. Existem várias opções para implementar isso. Obviamente, herança múltipla é uma. Mas a herança múltipla é bastante complicada de implementar. Mas não é realmente necessário aqui. Em vez disso, muitas linguagens implementam isso dividindo o mixin em uma interface, implementada pela classe e um repositório de implementações de métodos, que são injetados na própria classe ou é gerada uma classe base intermediária e são colocadas lá. Isso é implementado em Ruby e D , será implementado em Java 8 e pode ser implementado manualmente em C ++ usando o padrão de modelo curiosamente recorrente . O acima, no formato CRTP, se parece com:
e é usado como:
Isso não requer que nada seja declarado virtual como a classe base regular exigiria, portanto, se a interface for usada em modelos, deixa opções úteis de otimização em aberto. Observe que, em C ++, isso provavelmente ainda seria herdado como segundo pai, mas em idiomas que não permitem herança múltipla, ele é inserido na cadeia de herança única, por isso é mais parecido com
A implementação do compilador pode ou não evitar o despacho virtual.
Uma implementação diferente foi selecionada em C #. Em C #, as implementações são métodos estáticos de classe completamente separada e a sintaxe da chamada de método é adequadamente interpretada pelo compilador se um método de nome determinado não existir, mas um "método de extensão" for definido. Isso tem a vantagem de que métodos de extensão podem ser adicionados à classe já compilada e a desvantagem de que tais métodos não podem ser substituídos, por exemplo, para fornecer uma versão otimizada.
fonte
A resposta é que ele não funciona corretamente no C ++ no caso de conflitos no namespace. Veja isso . Para evitar conflitos de espaço para nome, você precisa fazer todo tipo de rotação com ponteiros. Trabalhei na MS na equipe do Visual Studio e, pelo menos em parte, o motivo pelo qual eles desenvolveram delegação foi evitar completamente a colisão de namespace. Anteriormente, eu havia dito que eles também consideravam as interfaces parte da solução de herança múltipla, mas eu estava enganado. As interfaces são realmente incríveis e podem ser feitas para trabalhar em C ++, FWIW.
A delegação trata especificamente da colisão de namespace: você pode delegar para 5 classes e todos os 5 exportarão seus métodos para o seu escopo como membros da primeira classe. Do lado de fora, é uma herança múltipla.
fonte