В C #, C ++ и Java, когда вы создаете конструктор, принимающий параметры, стандартный параметр без параметров исчезает. Я всегда только принимал этот факт, но теперь я начал задаваться вопросом, почему.
В чем причина такого поведения? Это просто «мера безопасности / догадка», говорящая «Если вы создали собственный конструктор, вы, вероятно , не хотите, чтобы этот неявный зависал»? Или у него есть техническая причина, которая делает невозможным его добавление компилятором, если вы сами создали конструктор?
c#
java
c++
default-constructor
olagjo
источник
источник
Foo() = default;
чтобы получить обратно по умолчанию.Ответы:
Нет никаких причин, по которым компилятор не мог бы добавить конструктор, если вы добавили свой собственный - компилятор мог делать практически все, что ему нужно! Тем не менее, вы должны посмотреть на то, что имеет больше смысла:
Таким образом, в каждом случае вы можете видеть, что поведение текущих компиляторов наиболее целесообразно с точки зрения сохранения вероятного намерения кода.
источник
Там, безусловно, нет технической причины, почему язык должен быть разработан таким образом.
Я вижу четыре реалистичных варианта:
Вариант 1 является несколько привлекательным, в том , что чем больше я код менее часто я действительно хочу конструктор без параметров. Однажды я должен посчитать, как часто я на самом деле заканчиваю с использованием конструктора по умолчанию ...
Вариант 2 У меня все хорошо.
Вариант 3 идет против потока как Java, так и C #, для остальной части языка. Нет ничего, что вы явно «удаляете», если только вы не рассчитываете сделать вещи более закрытыми, чем они были бы по умолчанию в Java.
Вариант 4 ужасен - вы абсолютно хотите иметь возможность форсировать конструкцию с определенными параметрами. Что бы
new FileStream()
вообще значило?Таким образом, в принципе, если вы принимаете предпосылку, что предоставление конструктора по умолчанию имеет смысл вообще, я считаю, что имеет смысл отключить его, как только вы предоставите свой собственный конструктор.
источник
struct
, к лучшему или к худшему.Редактировать. На самом деле, хотя то, что я говорю в своем первом ответе, действительно, это реальная причина.
Вначале был C. С не объектно-ориентированный (вы можете использовать ОО-подход, но он вам не помогает и ничего не обеспечивает).
Затем был C With Classes, который позже был переименован в C ++. C ++ является объектно-ориентированным и, следовательно, поощряет инкапсуляцию и обеспечивает инвариант объекта - при создании и в начале и в конце любого метода объект находится в допустимом состоянии.
Естественная вещь, которую нужно сделать с этим, состоит в том, чтобы обеспечить, чтобы класс всегда имел конструктор, чтобы гарантировать, что он запускается в допустимом состоянии - если конструктору не нужно ничего делать, чтобы гарантировать это, тогда пустой конструктор задокументирует этот факт. ,
Но цель с C ++ состояла в том, чтобы быть совместимым с C до такой степени, чтобы все действительные программы на C были, насколько это возможно, также действительными программами C ++ (больше не как активная цель, а эволюция C отдельно от C ++ означает, что она больше не выполняется ).
Одним из эффектов этого было дублирование функциональности между
struct
иclass
. Первые делают вещи C-способом (все общедоступно по умолчанию), а вторые делают вещи хорошим способом OO (все приватно по умолчанию, разработчик активно публикует то, что они хотят публично).Другая причина состоит в том, что для того, чтобы C
struct
, у которого не могло быть конструктора, потому что у C нет конструкторов, был бы действителен в C ++, для этого должен был быть смысл в подходе C ++. И поэтому, хотя отсутствие конструктора противоречило бы ОО-практике активного обеспечения инварианта, C ++ принял это, чтобы означать, что был конструктор по умолчанию без параметров, который вел себя так, как если бы он имел пустое тело.Все C
structs
теперь были действительными C ++structs
(что означало, что они были такими же, как C ++classes
со всем - члены и наследование - общедоступными), которые рассматривались извне, как если бы у них был один конструктор без параметров.Однако, если вы поместили конструктор в
class
илиstruct
, то вы делали это способом C ++ / OO, а не способом C, и не было необходимости в конструкторе по умолчанию.Так как это служило сокращением, люди продолжали использовать его, даже если совместимость не была возможна иначе (он использовал другие функции C ++, не в C).
Следовательно, когда появилась Java (основанная на C ++ во многих отношениях), а затем и C # (основанная на C ++ и Java по-разному), они сохранили этот подход, поскольку кодеры уже могут быть использованы.
Страуструп пишет об этом на своем языке программирования C ++ и тем более, уделяя больше внимания «почему» языка в «Проектировании и эволюции C ++» .
=== Оригинальный ответ ===
Допустим, этого не произошло.
Допустим, я не хочу конструктор без параметров, потому что я не могу перевести мой класс в осмысленное состояние без него. Действительно, это то, что может случиться
struct
в C # (но если вы не можете осмысленно использовать все нули и нулиstruct
в C #, вы в лучшем случае используете невидимую для оптимизации оптимизацию, а в противном случае имеете недостаток дизайна в использованииstruct
).Чтобы мой класс мог защитить свои инварианты, мне нужно специальное
removeDefaultConstructor
ключевое слово. По крайней мере, мне нужно создать частный конструктор без параметров, чтобы никакой вызывающий код не вызывал значение по умолчанию.Что еще больше усложняет язык. Лучше не делать этого.
В целом, лучше не думать о добавлении конструктора как об удалении по умолчанию, лучше о том, чтобы вообще не иметь конструктора как синтаксического сахара для добавления конструктора без параметров, который ничего не делает.
источник
Конструктор по умолчанию, без параметров, добавляется, если вы сами ничего не делаете для управления созданием объекта. После того, как вы создали единственный конструктор для управления, компилятор «отступает» и дает вам полный контроль.
Если это не так, вам понадобится какой-то явный способ отключить конструктор по умолчанию, если вы хотите, чтобы объекты можно было конструировать только через конструктор с параметрами.
источник
Это удобная функция компилятора. Если вы определяете конструктор с параметрами, но не определяете конструктор без параметров, вероятность того, что вы не хотите разрешать конструктор без параметров, намного выше.
Это касается многих объектов, которые просто не имеют смысла инициализировать пустым конструктором.
В противном случае вам придется объявить закрытый конструктор без параметров для каждого класса, который вы хотите ограничить.
На мой взгляд, нехорошо использовать конструктор без параметров для класса, для которого нужны параметры.
источник
Я думаю, что вопрос должен быть наоборот: почему вам не нужно объявлять конструктор по умолчанию, если вы не определили другие конструкторы?
Конструктор обязателен для нестатических классов.
Поэтому я думаю, что если вы не определили никаких конструкторов, сгенерированный конструктор по умолчанию - это просто удобная особенность компилятора C #, также ваш класс был бы недействительным без конструктора. Так что нет ничего плохого в том, чтобы неявно генерировать конструктор, который ничего не делает. Это выглядит чище, чем пустые конструкторы вокруг.
Если вы уже определили конструктор, ваш класс действителен, так почему компилятор должен считать, что вам нужен конструктор по умолчанию? Что делать, если вы не хотите один? Реализовать атрибут, чтобы сказать компилятору не генерировать конструктор по умолчанию? Я не думаю, что это было бы хорошей идеей.
источник
Конструктор по умолчанию может быть создан только тогда, когда у класса нет конструктора. Компиляторы написаны таким образом, чтобы обеспечить это только как механизм резервного копирования.
Если у вас есть параметризованный конструктор, вы можете не захотеть создавать объект с использованием конструктора по умолчанию. Если бы компилятор предоставил конструктор по умолчанию, вам пришлось бы написать конструктор без аргументов и сделать его закрытым, чтобы объекты не создавались без аргументов.
Кроме того, больше шансов на то, что вы забудете отключить или «приватизировать» конструктор по умолчанию, что приведет к трудному обнаружению потенциальной функциональной ошибки.
И теперь вам нужно явно определить конструктор без аргументов, если вы хотите, чтобы объект создавался по умолчанию или путем передачи параметров. Это строго проверено, и компилятор жалуется на иное, что гарантирует отсутствие здесь лазеек.
источник
посылка
Такое поведение можно рассматривать как естественное продолжение решения для классов иметь открытый конструктор по умолчанию без параметров . Основываясь на заданном вопросе, мы принимаем это решение как предпосылку и предполагаем, что в данном случае мы не ставим его под сомнение.
Способы удаления конструктора по умолчанию
Отсюда следует, что должен быть способ удалить открытый конструктор по умолчанию без параметров. Это удаление может быть выполнено следующими способами:
Выбор лучшего решения
Теперь мы спрашиваем себя: если нет конструктора без параметров, на что он должен быть заменен? и при каких типах сценариев мы хотели бы удалить открытый конструктор по умолчанию без параметров?
Вещи начинают падать на месте. Во-первых, он должен быть заменен конструктором с параметрами или непубличным конструктором. Во-вторых, сценарии, при которых вам не нужен конструктор без параметров:
Вывод
Там у нас это есть - именно два способа, которыми C #, C ++ и Java позволяют удалить открытый конструктор по умолчанию без параметров.
источник
= delete
для этой цели.Я думаю, что это обрабатывается компилятором. Если вы откроете
.net
сборку,ILDASM
вы увидите конструктор по умолчанию, даже если его нет в коде. Если вы определите параметризованный конструктор, конструктор по умолчанию не будет виден.На самом деле, когда вы определяете класс (не статический), компилятор предоставляет эту возможность, думая, что вы будете просто создавать экземпляр. И если вы хотите, чтобы какая-то конкретная операция выполнялась, у вас наверняка будет собственный конструктор.
источник
Это потому, что когда вы не определяете конструктор, компилятор автоматически генерирует для вас конструктор, который не принимает никаких аргументов. Когда вы хотите чего-то большего от конструктора, вы перезагружаете это. Это НЕ перегрузка функций. Таким образом, единственный конструктор, который теперь видит компилятор, это ваш конструктор, который принимает аргумент. Чтобы противостоять этой проблеме, вы можете передать значение по умолчанию, если конструктор передается без значения.
источник
Классу нужен конструктор. Это обязательное требование.
Я отвечу на ваш вопрос другим, почему мы всегда хотим конструктор без параметров по умолчанию? В некоторых случаях это нежелательно, поэтому разработчик может добавлять или удалять его по мере необходимости.
источник