C ++ Могу ли я использовать std :: unique_ptr с внедрением зависимости? - PullRequest
4 голосов
/ 01 ноября 2011

Я делал инъекцию зависимостей, используя необработанные указатели, и я решил преобразовать свой код для использования shared_ptr. Это работает, но мне интересно, если бы я мог использовать unique_ptr вместо этого? В моем примере ниже MyClass будет управлять сроком службы кредитных карт.

class PaymentProcessor
{
    PaymentProcessor(?? creditCardService):
      :creditCardService_(creditCardService)
      {

      }

private:
   CreditCardService *creditCardService_;     
}

class MyClass
{ 
public:
   void DoIt()
   {
     creditCardService_.reset(new VisaCardService());
     PaymentProcessor pp(creditCardService_);
     pp.ProcessPayment();
   }

private:   
   std::unique_ptr<CreditCardService> creditCardService_;
}

Можете ли вы передать unique_ptr другому классу, где другой класс просто "использует" указатель (не имея его ??)? Если это так, то это хорошая идея и какой тип параметра должен быть в конструкторе для PaymentProcessor?

UPDATE

В примере, как показано выше, можно альтернативно создать VisaCardService переменную в стеке и имеют PaymentProcessor Конструктор принять это в качестве опорного параметра. Кажется, это рекомендуемая практика C ++. Однако в случае, когда конкретный тип creditCardService_ не известен до времени выполнения (например, пользователь выбирает конкретную службу кредитных карт для использования во время выполнения), использует std::unique_ptr со ссылками лучшее решение?

1 Ответ

4 голосов
/ 01 ноября 2011

Можете ли вы передать unique_ptr другому классу, где другой класс просто «использовать» указатель (не владея им ??)?

В этом случае измените указатель на ссылку:

class PaymentProcessor
{
public:
    PaymentProcessor(CreditCardService & creditCardService_):
      :creditCardService_(creditCardService_)
      {
      }

private:
   CreditCardService &creditCardService_;     
};

   void DoIt()
   {
     creditCardService_.reset(new VisaCardService());
     PaymentProcessor pp(*creditCardService_);
     pp.ProcessPayment();
   }

Если вы все еще хотите использовать указатель, тогда вам нужно использовать get метод:

class PaymentProcessor
{
public:
    PaymentProcessor(CreditCardService * creditCardService_):
      :creditCardService_(creditCardService_)
      {
      }
private:
   CreditCardService *creditCardService_;     
};

   void DoIt()
   {
     creditCardService_.reset(new VisaCardService());
     PaymentProcessor pp(creditCardService_.get());
     pp.ProcessPayment();
   }
...