Как работать с std ::make_unique функцией и классами интерфейса?

#c #inheritance #interface #abstract-class #unique-ptr

#c #наследование #интерфейс #абстрактный класс #уникальный-ptr

Вопрос:

Предположим, мы хотим реализовать шаблон стратегии. У нас есть интерфейс Base и два производных класса — A и B . Экземпляры Doer класса могут выбирать между A ‘s и B ‘s методами do() . И вопрос в том, как завершить код, чтобы сделать так, как это должно быть.

 class Base {
  virtual void do() const = 0;
};

class A: public Base {
  void do() const override {};
};

class B: public Base {
  void do() const override {};
}

class Doer {
  public:
    Doer(std::unique_ptr<Base> b_ptr) : ptr(b_ptr) {}
    void do() const { ptr->do(); }
  private:
    std::unique_ptr<Base> ptr;
}

int main() {
  Doer doer(std::unique_ptr<Base>());
  doer.do();
  return 0;
}
  

Ответ №1:

 Doer doer(std::make_unique<A>()); // or std::make_unique<B>()
  

Вышесказанное в значительной степени это. std::unique_ptr очень сложно реализовать то же принуждение, что и исходный указатель, который он содержит.

Ответ №2:

В вашем коде есть три основные проблемы.

1) do является ключевым словом языка. Вы не можете использовать его в качестве идентификатора (например, имени функции)

2) вы принимаете b_ptr по значению, поэтому вам нужно перейти от него:

 Doer(std::unique_ptr<Base> b_ptr) : ptr(std::move(b_ptr)) {}
  

3) вы передаете пустой unique_ptr в Doer конструктор, что эквивалентно передаче nullptr . Вы также пытаетесь создать экземпляр базового класса. Это невозможно, потому что Base это чисто виртуальный класс. Использовать make_unique с производным типом:

 Doer doer(std::make_unique<A>());