Как передать объект по значению? - PullRequest
7 голосов
/ 26 сентября 2011
import std.stdio;

class IntegerContainer
{
    public int Integer = 1;
}

void DoubleInteger(IntegerContainer Container)
{
    Container.Integer *= 2;
}

void main()
{
    IntegerContainer Container = new IntegerContainer; // Internal integer defaults to one.
    DoubleInteger(Container); // Internal integer changes to two inside the function.
    writefln(Container.Integer); // Prints "2."
}

В D, ссылка против значения является признаком типа, а не параметра функции.Исходя из C ++, мне это очень плохо.

Похоже, есть ключевое слово ref для принудительной передачи по ссылке для функций, принимающих struct s.Есть ли такой эквивалент для передачи class es по значению?

Например, допустим, я хочу создать функцию-функцию, которая возвращает отсортированную копию пользовательского класса контейнера.В C ++ это так же просто, как использовать Foo Sorted(Foo Object), в отличие от Foo Sort(Foo& Object).Я не вижу способа сделать это в D без копирования объекта вручную.

Ответы [ 3 ]

11 голосов
/ 26 сентября 2011

Классы являются ссылочными типами по дизайну.Они не должны передаваться по значению.Точно так же с Java и C #.Однако, в отличие от Java и C #, D также имеет полноценные определяемые пользователем типы значений, так как имеет структуры (в C # тоже есть структуры, но они намного более ограничены).Тот факт, что C ++ объединяет эти две причины, вызывает проблемы, такие как срезы объектов .

Теперь, очевидно, бывают случаев, когда вы хотите скопировать ссылочный тип.Решение этой проблемы - клонирование .Вы даете своему классу функцию clone, которая возвращает копию объекта, к которому она обращена.Таким образом, вы можете скопировать его, когда вам нужно, и он будет скопирован только тогда, когда вам это нужно.Java и C # имеют стандартную функцию clone, которую реализует большинство типов, но по какой-то причине D не имеет.Я не уверен почему.Но все равно достаточно легко самостоятельно объявить такую ​​функцию для своих типов.Это просто не будет на Object, что позволило бы вам использовать его практически на любом объекте класса, не заботясь о том, каким был реальный тип, как вы можете делать в Java и C #.Вместо этого вы всегда можете создать конструктор копирования, если хотите, но он менее гибок, потому что вы должны знать тип копируемого объекта, тогда как с clone это может быть любой тип, производный от типа, cloneвозвращает (что будет Object в случае Java и C #, но будет тем, что вы решите в D, так как функция нестандартная).

4 голосов
/ 26 сентября 2011

Да, просто используйте структуру вместо класса.

Но если вы хотите скопировать объект , то вам нужно реализовать клонирование самостоятельно.Обратите внимание, что дизайнеры D не придумали это;это точно так же, как в C #, и очень похоже на Java.Цель состоит в том, чтобы предотвратить чрезмерное копирование объектов, что считается недостатком C ++ (поскольку он очень скрыт в коде).

3 голосов
/ 26 сентября 2011

Даже в C ++ это:

Foo Sorted(Foo Object)

не так уж полезно.Что, если Объект уже отсортирован, и вам не нужно создавать копию?

В D вам потребуется предоставить clone() некоторых таких для вашего класса и вызвать их при необходимости.1008 * В противном случае используйте структуры, как упомянул Мехрдад.

Редактировать: Не ясно, что именно должно делать "копирование объекта".Если у него есть массив объектов внутри, должен ли он клонировать этот массив?А как насчет ссылок на объекты, которые он содержит?Хорошо, что мсье Вальтер Брайт, автор D, по умолчанию не обеспечивал копирование экземпляров классов.

...