Инициализировать указатель через функцию - PullRequest
6 голосов
/ 10 июня 2010

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

Order* order1 = NULL;

затем

order1 = order(customer1, product2);

, который вызывает

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

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

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

order1 = new Order(customer, product);

Ответы [ 6 ]

8 голосов
/ 10 июня 2010

Init to NULL

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

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

Order * order1 = order(...);

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

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

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

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

(1) Проверка, которую не может выполнить конструктор Ордена.Order может поступать из сторонней библиотеки и не может быть изменен, либо для экземпляра необходимо добавить проверку, которая не входит в область действия 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);             
}   

Тем не менее, я бы не стал делать это в общих чертах вслепую.

3 голосов
/ 10 июня 2010

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

2 голосов
/ 10 июня 2010

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

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

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

2 голосов
/ 10 июня 2010

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

1 голос
/ 22 июня 2010

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

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

Order* order1 = order(customer1, product2);

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

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

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

0 голосов
/ 10 июня 2010

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

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