Инициализируйте указатель через функцию

Я просматривал код своего учителя, когда я споткнулся через это:

Order* order1 = NULL;

затем

order1 = order(customer1, product2);

который звонит

Order* order(Customer* customer, Product* product)
{
    return new Order(customer, product);
}

Это похоже на глупый код. Я не уверен, почему, но учитель инициализировал все указатели на ПУСТОЙ УКАЗАТЕЛЬ вместо того, чтобы объявить их сразу же (смотрящий на код, это совершенно возможно, но он выбрал не к).

Мой вопрос: этот хороший или приемлемый код? Вызов функции обладает какими-либо преимуществами по вызову конструктора explicitely? И как делает новую работу в этом случае? Могу я воображать код теперь как отчасти как:

order1 = new Order(customer, product);

6
задан IAE 10 June 2010 в 06:01
поделиться

6 ответов

Инициализируется на NULL

[править], поскольку есть правильное обсуждение, я немного изменил порядок опций, чтобы выделить рекомендуемый вариант.

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

Order * order1 = order(...);

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

Order * order1;  // Oh no! not initialized!
// ... some code
order1 = order(...);

order1 должен быть инициализирован значением NULL, чтобы предотвратить общие ошибки, возникающие с неинициализированными переменными, которые легко возникают, когда // некоторые изменения кода .

Заводской метод
Опять же, здесь есть еще одна устойчивость к изменениям: требования для создания экземпляра Order могут измениться. Я могу сразу придумать два сценария:

(1) Проверка, которую не может выполнить конструктор Order. Заказ может поступать из сторонней библиотеки и не может быть изменен, либо при создании экземпляра требуется добавить проверку, выходящую за рамки Приказа :

Order* order(Customer* customer, Product* product)             
{      
    // Order can't validate these, since it doesn't "know" the database       
    database.ValidateCustomer(customer); // throws on error
    database.ValidateProduct(product); // throws on error

    return new Order(customer, product);             
}   

(2) Вы может понадобиться порядок, который ведет себя иначе.

class DemoOrder : public Order  { ... }

Order* order(Customer* customer, Product* product)             
{             
    if (demoMode)
      return new DemoOrder(customer, product); // doesn't write to web service
    else
      return new Order(customer, product);             
}   

Однако я бы не стал слепо делать это общим шаблоном.

8
ответ дан 8 December 2019 в 14:40
поделиться

Если это действительно все важный код, я не вижу пользы для функции или начального значения NULL. new работает так, как всегда. Он создает Order и возвращает указатель на него, который, в свою очередь, возвращается order .

2
ответ дан 8 December 2019 в 14:40
поделиться

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

3
ответ дан 8 December 2019 в 14:40
поделиться

Приведенный код может быть важным, если присвоение NULL происходит в одной функции, например, в конструкторе, а присвоение, вызывающее new, происходит в другой функции. Вот три причины;

  • Если параметры клиента и товара могут быть недоступны, когда вызывается order = NULL.
  • Значение NULL может быть важным в промежуточный момент, чтобы дать знать другим функциям, что заказ еще не создан.
  • Если класс Order занимал много ресурсов, отсрочка его инициализации могла бы быть полезной.

Лучше всего спросить своего учителя, почему он поступил именно так. Иногда очевидные выводы не являются правильными.

2
ответ дан 8 December 2019 в 14:40
поделиться

Для данного кода разницы нет. Лучше инициализировать объект order вновь созданным объектом в одном месте. Это позволит избежать использования переменной order, инициализированной значением NULL

0
ответ дан 8 December 2019 в 14:40
поделиться

Если вещи действительно такие, как вы их описываете, тогда код вашего учителя иллюстрирует некоторые довольно плохие практики программирования.

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

Order* order1 = order(customer1, product2);

То же самое можно было бы применить к коду C99, поскольку C99 позволяет объявлять переменную в середине блока.

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

Я бы сказал, что код C ++ вашего учителя страдает некоторыми вредными привычками, перенесенными из C.

1
ответ дан 8 December 2019 в 14:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: