Почему в Java нет списков инициализаторов, как в C ++? - PullRequest
53 голосов
/ 23 августа 2011

В C ++ вы можете использовать список инициализаторов, чтобы инициализировать поля класса до того, как конструктор начнет работать.Например:

Foo::Foo(string s, double d, int n) : name(s), weight(d), age(n) {
    // Empty; already handled!
}

Мне любопытно, почему в Java нет подобной функции.Согласно Core Java: Том 1 :

C ++ использует этот специальный синтаксис для вызова конструкторов полей.В Java это не нужно, потому что у объектов нет подобъектов, только указатели на другие объекты.

Вот мои вопросы:

  1. Что ониозначает "потому что объекты не имеют подобъектов?"Я не понимаю, что такое подобъект (я пытался найти его);они означают создание экземпляра подкласса, который расширяет суперкласс?

  2. Что касается того, почему у Java нет списков инициализаторов, таких как C ++, я бы предположил, что причина в том, что все поля уже инициализированыпо умолчанию в Java, а также потому, что Java использует ключевое слово super для вызова конструктора супер (или базового в C ++ lingo) -класса.Это правильно?

Ответы [ 3 ]

97 голосов
/ 23 августа 2011

В C ++ списки инициализаторов необходимы из-за нескольких языковых функций, которые либо отсутствуют в Java, либо работают по-другому в Java:

  1. const: В C ++ вы можете определить поля, помеченные const, которые не могут быть назначены и должны быть инициализированы в списке инициализаторов.В Java есть поля final, но вы можете назначить поля final в теле конструктора.В C ++ присвоение полю const в конструкторе недопустимо.

  2. Ссылки : В C ++ ссылки (в отличие от указателей) должны быть инициализированы впривязать к некоторому объекту.Запрещено создавать ссылку без инициализатора.В C ++ способ, которым вы указываете это, с помощью списка инициализаторов, поскольку, если бы вы ссылались на ссылку в теле конструктора без предварительной инициализации, вы бы использовали неинициализированную ссылку.В Java ссылки на объекты ведут себя как указатели C ++ и могут быть назначены после создания.По умолчанию они null.

  3. Прямые подобъекты .В C ++ объект может содержать объект непосредственно как поля, тогда как в Java объекты могут содержать только ссылки на эти объекты.То есть в C ++, если вы объявляете объект, который имеет string в качестве члена, пространство для хранения этой строки встроено непосредственно в пространство для самого объекта, в то время как в Java вы просто получаете пространство для ссылки на некоторыедругой String объект хранится в другом месте.Следовательно, C ++ должен предоставить вам способ дать этим субобъектам начальные значения, так как в противном случае они просто остались бы неинициализированными.По умолчанию он использует конструктор по умолчанию для этих типов, но если вы хотите использовать другой конструктор или конструктор по умолчанию недоступен, список инициализаторов дает вам возможность обойти это.В Java вам не нужно беспокоиться об этом, потому что ссылки по умолчанию будут null, и вы можете назначить их для ссылки на объекты, на которые вы действительно хотите, чтобы они ссылались.Если вы хотите использовать конструктор не по умолчанию, вам не нужен специальный синтаксис для него;просто установите ссылку на новый объект, инициализированный с помощью соответствующего конструктора.

В тех немногих случаях, когда Java может хотеть списки инициализатора (например, вызывать конструкторы суперкласса или присваивать значения по умолчанию егоfields), это обрабатывается двумя другими языковыми функциями: ключевым словом super для вызова конструкторов суперкласса и тем фактом, что объекты Java могут давать своим полям значения по умолчанию в точке, в которой они объявлены.Поскольку C ++ имеет множественное наследование, наличие одного ключевого слова super не будет однозначно ссылаться на один базовый класс, и до C ++ 11 C ++ не поддерживал инициализаторы по умолчанию в классе и должен был полагаться на списки инициализаторов.

Надеюсь, это поможет!

9 голосов
/ 23 августа 2011

C ++

Есть разница между

ClassType t(initialization arguments);

и

ClassType * pt;

Последний не нужно инициализировать (установить в NULL). Первый делает. Думайте об этом как о целом числе. Вы не можете иметь int без значения, НО вы можете иметь указатель int без значения.

Итак, когда у вас есть:

class ClassType
{
    OtherClass value;
    OtherClass * reference;
};

Тогда объявление:

ClassType object;

автоматически создает экземпляр OtherClass в value. Поэтому, если OtherClass имеет инициализацию, это должно быть сделано в конструкторе ClassType. Однако reference является просто указателем (адресом в памяти) и может оставаться неинициализированным. Если вы хотите экземпляр OtherClass, вы должны использовать

object.reference = new OtherClass(initialization arguments);

Java

Есть только

class ClassType
{
    OtherClass reference;
}

Это эквивалентно указателю в C ++. В этом случае, когда вы делаете:

ClassType object = new ClassType();

Вы автоматически не создаете экземпляр OtherClass. Следовательно, вам не нужно ничего инициализировать в конструкторе, если вы этого не хотите. Если вам нужен объект OtherClass, вы можете использовать

object.reference = new OtherClass();
1 голос
/ 23 августа 2011

Поскольку Java не нуждается в них для разрешения инициализации полей, тип которых не имеет нулевого значения.

В C ++

class C {
  D d;
}

без инициализатора члена для d, * 1007будет вызвано *, что делает невозможным инициализацию поля, если для D нет нулевого типа.Это может произойти, когда D::D() явно объявлено private.

В Java существует известное нулевое значение для всех ссылочных типов, null, поэтому поле всегда может бытьбыть инициализированным.

Java также выполняет большую часть работы, чтобы удостовериться, * что все final поля инициализируются перед первым использованием и до завершения конструктора, поэтому в Java есть требование, такое как * ++ 1019 * поля C ++ для инициализации поля.требование, это просто перегружает this.fieldName = <expression> в теле конструктора для обозначения инициализации поля.

  • : исключения по модулю, генерируемые в ctor, переопределенные вызовы методов из базового класса и т. д.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...