Почему конструкторы не возвращают значения?



Пожалуйста, скажите мне, почему конструктор не возвращает никакого значения. Мне нужна идеальная техническая причина, чтобы объяснить моим студентам, почему конструктор не имеет никакого возвращаемого типа.

774   17  

17 ответов:

что на самом деле происходит с конструктором, так это то, что среда выполнения использует данные типа, созданные компилятором, чтобы определить, сколько места требуется для хранения экземпляра объекта в памяти, будь то в стеке или в куче.

Это пространство включает в себя все переменные-члены и vtbl. После выделения этого пространства конструктор вызывается как внутренняя часть процесса создания и инициализации экземпляра для инициализации содержимого полей.

потом, когда конструктор завершает работу, среда выполнения возвращает вновь созданный экземпляр. Таким образом, причина, по которой конструктор не возвращает значение, заключается в том, что он не вызывается непосредственно вашим кодом, он вызывается кодом выделения памяти и инициализации объекта во время выполнения.

его возвращаемое значение (если оно действительно имеет его при компиляции до машинного кода) непрозрачно для пользователя - поэтому вы не можете его указать.

Ну, в некотором смысле, это возвращает экземпляр, который только что был построен.

вы даже называете это так, например Java

 Object o = new Something();

который выглядит так же, как вызов "обычного" метода с возвращаемым значением

 Object o = someMethod();

(Я склоняюсь к C++, поэтому в отношении других языков, возьмите это с зерном соли.)

короткий ответ: вы не хотите явно проверять успех для каждой отдельной конструкции объекта в вашем коде.

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

void f()
{
  std::string s;
}

нет никакого способа для конструктора s (std::string::string()) для возвращения любое значение. Либо он преуспевает - тогда мы можем использовать объект, либо он выбрасывает исключение - у нас никогда не будет возможности попробовать его использовать.

ИМО, так и должно быть.

как конструктор должен возвращать возвращаемое значение? Элемент new оператор возвращает вновь созданный экземпляр. Вы не вызываете конструктор, newэто делает.

MyClass instance = new MyClass();

если конструктор возвращает значение, например, так:

public int MyClass()
{
    return 42;
}

где бы вы получили целое число?

при вызове конструктора возвращаемое значение-это новый объект:

Point pt = new Point(1,2);

но в самом конструкторе вы фактически не создаете и не возвращаете объект; он был создан до запуска вашего кода, Вы просто устанавливаете начальные значения.

Point::Point(int x, int y) {
  this->x = x;
  this->y = y;
}

отсутствие возвращаемого типа, отражает тот факт, что конструкторы используются иначе, чем другие функции. Возвращаемый тип null, хотя технически точно, не отражает хорошо тот факт, что код используется как будто он возвращает объект. Однако любой другой тип возврата указывает, что ваш код должен return что-то в конце, что тоже неверно.

конструктор-это метод автоматически вызывается при инициализации нового экземпляра объекта.

этот метод существует, если вам нужно инициализировать объект в заданное состояние и запустить несколько методов по умолчанию.

на самом деле вы можете себе представить, что конструктор всегда возвращает экземпляр созданного объекта, который был бы хорошим изображением.

все ответы смещены в сторону C++ / Java. нет никаких причин, по которым конструктор не возвращает значение, отличное от языкового дизайна.

посмотреть конструктор в более широком смысле: это функция, которая создает новый объект. вы можете написать совершенно допустимые конструкторы в C:

typedef struct object object;
int object_create( object **this );

Это идеальный ООП в C и конструктор возвращает значение (это также можно назвать фабрикой, но имя зависит от намерения).

однако, чтобы создайте объект автоматически (например, чтобы удовлетворить некоторому приведению типа или преобразованию), должны быть определены некоторые правила. в C++ существует конструктор без аргументов, который выводится компилятором, если он не определен.


обсуждение шире, чем мы думаем. Объектно-ориентированное программирование-это имя, которое описывает мышление о программировании. вы можете иметь OO практически на любом языке: все, что вам нужно, это структуры и функции. основные языки, такие как C++ и Java, настолько распространены, что мы думаем, что они определяют "путь". теперь посмотрите на модель OO в Ada: она далека от модели C++, но все еще является OO. я уверен, что такие языки, как Lisp, имеют некоторые другие способы выполнения OO.

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

несмотря на то, что реализация VM конструктора не должна возвращать какое - либо значение, на практике это происходит-ссылка на новый объект. Тогда было бы синтаксически странно и / или запутанно хранить одну или обе ссылки на новый объект и дополнительное возвращаемое значение в одном операторе.

конструктор не вызывается непосредственно кодом пользователя. Он вызывается кодом выделения памяти и инициализации объекта во время выполнения. Его значение не видно пользователю.

в случае C#, синтаксис для объявления объекта:

classname objectname= new constructor();

согласно этой строке, если мы используем оператор присваивания (=), то он должен возвращать некоторое значение. Но основная цель конструктора-присвоить значения переменным, поэтому при использовании нового ключевого слова он создает экземпляр этого класса, а конструктор присваивает значения переменной для этого конкретного экземпляра объекта, поэтому конструктор возвращает назначенные значения для экземпляра этих объектов.

мы не можем вызывать конструкторы самостоятельно. Вместо этого они автоматически вызываются при создании объектов. Например:

MyDate md = new Mydate(22,12,2012);

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

из того, что я знаю о методологиях проектирования OO, я бы сказал следующее:

1) позволяя конструктору возвращать значение, разработчик фреймворка позволит программе аварийно завершить работу в тот момент, когда возвращаемое значение не обрабатывается. Чтобы сохранить целостность рабочего процесса программы, недопустимость возврата значения из инициализации объекта является допустимым решением. Вместо этого, дизайнер язык бы предложить/заставить кодеров использовать геттер/сеттер - доступ методы.

2)Разрешение объекту возвращать значение при инициализации также открывает возможные утечки информации. Особенно при наличии нескольких уровней или модификаций доступа, применяемых к переменным / методам.

Как вы знаете, что при создании объекта конструктор будет автоматически вызван, так что теперь представьте, что конструктор возвращает значение int. Так что код должен быть таким...

Class ABC
{
     int i;
public:
     int ABC()
     {
        i=0;
        return i;
     }
     .......
};
int main()
{
    int k= ABC abc; //constructor is called so we have to store the value return by it
    ....
}

но как вы знаете, что stament нравится int k= ABC abc; невозможно ни на одном языке программирования. Надеюсь, вы можете понять.

Я нашел его полезным

эта путаница возникает из предположения, что конструкторы так же, как и любые другие функции/методы, определенные классом. Нет, это не так.

конструкторы являются лишь частью процесса создания объекта. Они не вызываются как другие функции-члены.

Я бы использовал Java в качестве своего языка в ответе.

class SayHelloOnCreation {
     public SayHelloOnCreation() {
         System.out.println("Hello, Thanks For Creating me!");
     }
}

class Test {
     public static void main(String[]args) { 
         SayHelloOnCreation thing = new SayHelloOnCreation(); //This line here, produces an output - Hello, Thanks For Creating me!
     }
}

теперь давайте посмотрим, что происходит здесь. в Java, мы используем новая ключевое слово для создания экземпляра класса. И как вы можете видеть в коде, в строке SayHelloOnCreation thing = new SayHelloOnCreation ();, выражение после выполнения оператора присваивания перед выполнением присваивания. Так что с помощью ключевого слова новая мы вызываем конструктор класса (SayHelloOnCreation ()) и этот конструктор создает объект в куче Java. После создания объекта, ссылка на этот объект присваивается вещь ссылка типа SayHelloOnCreation.

точка что я пытаюсь сохранить здесь, так это то, что если конструкторам было разрешено иметь тип возврата,во-первых сильно типизированный характер языка будет скомпрометирован (помните, что я говоря о Java здесь).

во-вторых объект класса SayHelloOnCreation создается здесь, поэтому по умолчанию я думаю, что конструктор возвращает ссылку того же типа, чтобы избежать ClassCastException.

таким образом, причина, по которой конструктор не возвращает значение, заключается в том, что он не вызывается непосредственно вашим кодом, он вызывается кодом выделения памяти и инициализации объекта во время выполнения. Его возвращаемое значение (если оно действительно есть при компиляции до машинного кода) непрозрачно для пользователя - поэтому вы не можете его указать.

Comments

    Ничего не найдено.