Я просматривал код своего учителя, когда я споткнулся через это:
Order* order1 = NULL;
затем
order1 = order(customer1, product2);
который звонит
Order* order(Customer* customer, Product* product)
{
return new Order(customer, product);
}
Это похоже на глупый код. Я не уверен, почему, но учитель инициализировал все указатели на ПУСТОЙ УКАЗАТЕЛЬ вместо того, чтобы объявить их сразу же (смотрящий на код, это совершенно возможно, но он выбрал не к).
Мой вопрос: этот хороший или приемлемый код? Вызов функции обладает какими-либо преимуществами по вызову конструктора explicitely? И как делает новую работу в этом случае? Могу я воображать код теперь как отчасти как:
order1 = new Order(customer, product);
Инициализируется на 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);
}
Однако я бы не стал слепо делать это общим шаблоном.
Если это действительно все важный код, я не вижу пользы для функции или начального значения NULL. new
работает так, как всегда. Он создает Order и возвращает указатель на него, который, в свою очередь, возвращается order
.
Мне кажется, что ваш учитель - старый программист на C, который не совсем избавился от некоторых своих старых привычек. Раньше вам приходилось объявлять все переменные в начале функции, поэтому нет ничего необычного в том, что некоторые старожилы все еще делают это.
Приведенный код может быть важным, если присвоение NULL происходит в одной функции, например, в конструкторе, а присвоение, вызывающее new
, происходит в другой функции. Вот три причины;
order = NULL
. Лучше всего спросить своего учителя, почему он поступил именно так. Иногда очевидные выводы не являются правильными.
Для данного кода разницы нет. Лучше инициализировать объект order вновь созданным объектом в одном месте. Это позволит избежать использования переменной order, инициализированной значением NULL
Если вещи действительно такие, как вы их описываете, тогда код вашего учителя иллюстрирует некоторые довольно плохие практики программирования.
Ваш вопрос помечен как C ++. В C ++ правильным методом было бы переместить объявление переменной в точку, где она может быть инициализирована значимо. Т.е. он должен был выглядеть следующим образом
Order* order1 = order(customer1, product2);
То же самое можно было бы применить к коду C99, поскольку C99 позволяет объявлять переменную в середине блока.
В коде C объявление должно быть размещено в начале блока, что может привести к ситуациям, когда вы не можете осмысленно инициализировать переменную в точке объявления.Некоторые люди считают, что в этом случае вы должны инициализировать переменную с помощью something , чего угодно, только чтобы сохранить ее инициализированной, а не оставлять ее неинициализированной. Я могу уважать это как вопрос личных предпочтений, покупать лично считаю это контрпродуктивным. Он мешает оптимизации компилятора и имеет тенденцию скрывать ошибки, выметая их под ковер (вместо того, чтобы поощрять правильные исправления).
Я бы сказал, что код C ++ вашего учителя страдает некоторыми вредными привычками, перенесенными из C.