Em C #, C ++ e Java, quando você cria um construtor que aceita parâmetros, o padrão sem parâmetros desaparece. Sempre aceitei esse fato, mas agora comecei a me perguntar por quê.
Qual o motivo desse comportamento? É apenas uma "medida / palpite de segurança" dizendo "Se você criou um construtor próprio, provavelmente não quer este implícito por aí"? Ou ele tem uma razão técnica que torna impossível para o compilador adicionar uma depois que você mesmo cria um construtor?
c#
java
c++
default-constructor
olagjo
fonte
fonte
Foo() = default;
para recuperar o padrão.Respostas:
Não há razão para que o compilador não possa adicionar o construtor se você adicionou o seu - o compilador pode fazer praticamente o que quiser! No entanto, você deve observar o que faz mais sentido:
Portanto, em cada caso, você pode ver que o comportamento dos compiladores atuais faz mais sentido em termos de preservar a intenção provável do código.
fonte
Certamente não há razão técnica para o idioma ter que ser projetado dessa maneira.
Existem quatro opções um tanto realistas que posso ver:
A opção 1 é um pouco atraente, pois quanto mais eu codigo, menos frequentemente quero realmente um construtor sem parâmetros. Algum dia, devo contar quantas vezes realmente acabo usando um construtor padrão ...
Opção 2 Estou bem com.
A opção 3 vai contra o fluxo de Java e C # para o restante da linguagem. Nunca há nada que você "remova" explicitamente, a menos que conte explicitamente tornando as coisas mais privadas do que seriam por padrão em Java.
A opção 4 é horrível - você absolutamente deseja poder forçar a construção com determinados parâmetros. O que
new FileStream()
significaria?Então, basicamente, se você aceitar a premissa de que fornecer um construtor padrão faz algum sentido, acredito que faz muito sentido suprimi-lo assim que você fornecer seu próprio construtor.
fonte
struct
s, para melhor ou para pior.Editar. Na verdade, enquanto o que digo na minha primeira resposta é válido, esse é o verdadeiro motivo .:
No início, havia C. C não é orientado a objetos (você pode adotar uma abordagem OO, mas não ajuda ou aplica nada).
Havia C With Classes, que mais tarde foi renomeado para C ++. O C ++ é orientado a objetos e, portanto, incentiva o encapsulamento e garante a invariância de um objeto - na construção e no início e no final de qualquer método, o objeto está em um estado válido.
A coisa natural a fazer com isso é impor que uma classe sempre tenha um construtor para garantir que ele inicie em um estado válido - se o construtor não precisar fazer nada para garantir isso, o construtor vazio documentará esse fato .
Mas um objetivo com C ++ era ser compatível com C, a ponto de, na medida do possível, todos os programas C válidos também serem programas C ++ válidos (não é mais um objetivo ativo, e a evolução de C separada para C ++ significa que ele não é mais válido). )
Um efeito disso foi a duplicação na funcionalidade entre
struct
eclass
. O primeiro fazendo as coisas da maneira C (tudo público por padrão) e o segundo fazendo as coisas de uma maneira OO (tudo privado por padrão, o desenvolvedor torna público o que quer que seja público).Outra é que, para um C
struct
, que não poderia ter um construtor porque C não possui construtores, para ser válido em C ++, era necessário que houvesse um significado para isso na maneira como o C ++ olhava. E assim, embora não ter um construtor fosse contra a prática OO de garantir ativamente um invariável, o C ++ entendeu que isso significava que havia um construtor sem parâmetros padrão que agia como se tivesse um corpo vazio.Todos os C
structs
agora eram C ++ válidosstructs
(o que significava que eram iguais a C ++classes
com tudo - membros e herança - público) tratados externamente como se tivesse um construtor único e sem parâmetros.Se, no entanto, você colocou um construtor em a
class
oustruct
, então estava fazendo as coisas da maneira C ++ / OO em vez da maneira C, e não havia necessidade de um construtor padrão.Como funcionava como um atalho, as pessoas continuavam usando-o mesmo quando a compatibilidade não era possível de outra maneira (ele usava outros recursos do C ++ que não estavam em C).
Portanto, quando o Java surgiu (baseado em C ++ de várias maneiras) e depois em C # (baseado em C ++ e Java de maneiras diferentes), eles mantiveram essa abordagem como algo que os codificadores já podem estar acostumados.
Stroustrup escreve sobre isso em sua linguagem de programação The C ++ e, mais ainda, com mais foco nos "porquês" da linguagem em The Design and Evolution of C ++ .
=== Resposta original ===
Digamos que isso não aconteceu.
Digamos que eu não queira um construtor sem parâmetros, porque não posso colocar minha classe em um estado significativo sem um. Na verdade, isso é algo que pode acontecer com o
struct
C # (mas se você não pode fazer uso significativo de todos os zeros e nulosstruct
no C #, na melhor das hipóteses, você usa uma otimização não visível ao público e, caso contrário, possui uma falha de design no usostruct
).Para tornar minha classe capaz de proteger seus invariantes, preciso de uma
removeDefaultConstructor
palavra-chave especial . No mínimo, eu precisaria criar um construtor privado sem parâmetros para garantir que nenhum código de chamada chame o padrão.O que complica ainda mais a linguagem. Melhor não fazer isso.
Em suma, é melhor não pensar em adicionar um construtor como removendo o padrão, melhor pensar em não ter nenhum construtor como açúcar sintático para adicionar um construtor sem parâmetros que não faz nada.
fonte
O construtor padrão, sem parâmetros, é adicionado se você não fizer nada para assumir o controle sobre a criação de objetos. Depois de criar um único construtor para assumir o controle, o compilador "recua" e permite que você tenha o controle total.
Se não fosse assim, você precisaria de uma maneira explícita de desabilitar o construtor padrão se desejar que os objetos sejam construtíveis por meio de um construtor com parâmetros.
fonte
É uma função de conveniência do compilador. Se você definir um construtor com parâmetros, mas não definir um construtor sem parâmetros, a possibilidade de não querer permitir um construtor sem parâmetros é muito maior.
Este é o caso de muitos objetos que simplesmente não fazem sentido inicializar com um construtor vazio.
Caso contrário, você teria que declarar um construtor privado sem parâmetros para cada classe que deseja restringir.
Na minha opinião, não é bom estilo permitir um construtor sem parâmetros para uma classe que precisa de parâmetros para funcionar.
fonte
Eu acho que a pergunta deve ser o contrário: por que você não precisa declarar um construtor padrão se não definiu outros construtores?
Um construtor é obrigatório para classes não estáticas.
Então, eu acho que se você não definiu nenhum construtor, o construtor padrão gerado é apenas um recurso conveniente do compilador C #, também sua classe não seria válida sem um construtor. Portanto, nada de errado em gerar implicitamente um construtor que não faz nada. Certamente parece mais limpo do que ter construtores vazios por toda parte.
Se você já definiu um construtor, sua classe é válida, então por que o compilador deve assumir que você deseja um construtor padrão? E se você não quiser um? Implementar um atributo para informar ao compilador para não gerar esse construtor padrão? Eu não acho que seria uma boa ideia.
fonte
O construtor padrão pode ser construído apenas quando a classe não tiver um construtor. Os compiladores são escritos de maneira a fornecer isso apenas como um mecanismo de backup.
Se você tiver um construtor parametrizado, talvez não deseje que um objeto seja criado usando o construtor padrão. Se o compilador fornecesse um construtor padrão, você teria que escrever um construtor no-arg e torná-lo privado para impedir que objetos fossem criados usando nenhum argumento.
Além disso, haveria maiores chances de você esquecer de desabilitar ou privatizar o construtor padrão, causando um erro funcional potencial difícil de detectar.
E agora você precisa definir explicitamente um construtor no-arg se quiser que um objeto seja criado da maneira padrão ou passando parâmetros. Isso é fortemente verificado e o compilador reclama de outra maneira, garantindo assim nenhuma brecha aqui.
fonte
Premissa
Esse comportamento pode ser visto como uma extensão natural da decisão de as classes terem um construtor público sem parâmetros padrão . Com base na pergunta feita, tomamos essa decisão como premissa e assumimos que não a estamos questionando neste caso.
Maneiras de remover o construtor padrão
Daqui resulta que deve haver uma maneira de remover o construtor público sem parâmetros padrão. Essa remoção pode ser realizada das seguintes maneiras:
Selecionando a melhor solução
Agora nos perguntamos: se não há construtor sem parâmetros, o que deve ser substituído? e Em que tipos de cenários queremos remover o construtor público sem parâmetros padrão?
As coisas começam a se encaixar. Primeiro, ele deve ser substituído por um construtor por parâmetros ou por um construtor não público. Em segundo lugar, os cenários nos quais você não deseja um construtor sem parâmetros são:
Conclusão
Aqui temos - exatamente as duas maneiras pelas quais C #, C ++ e Java permitem a remoção do construtor público sem parâmetros padrão.
fonte
= delete
para esse fim.Eu acho que isso é tratado pelo compilador. Se você abrir a
.net
montagemILDASM
, verá o construtor padrão, mesmo que não esteja no código. Se você definir um construtor parametrizado, o construtor padrão não será visto.Na verdade, quando você define a classe (não estática), o compilador fornece esse recurso pensando que você estará apenas criando uma instância. E se você deseja que uma operação específica seja executada, certamente terá seu próprio construtor.
fonte
É porque quando você não define um construtor, o compilador gera automaticamente um construtor para você, que não aceita argumentos. Quando você quer algo mais fora de um construtor, você o substitui. Isso NÃO é sobrecarga de função. Portanto, o único construtor que o compilador vê agora é o seu construtor, que aceita um argumento. Para combater esse problema, você pode passar um valor padrão se o construtor for passado sem nenhum valor.
fonte
Uma classe precisa de um construtor. É requisito obrigatório.
Vou responder a sua pergunta com outra, por que queremos sempre um construtor sem parâmetros padrão? há casos em que isso não é desejado; portanto, o desenvolvedor tem o controle de adicionar ou remover conforme necessário.
fonte