在 c++ 中使用unique_ptr的工厂模式



我有一个 c++ 的旧工厂实现,我想在其中使用唯一的指针而不是原始指针。我的代码的一个最小示例如下。我有一个基类A,以及一个派生类B。在main()中,我在A中将1传递给create方法,现在b1的类型更改为B

#include <iostream>
#include <map>
class A {
 public:
  A() {}
  virtual void Foo() {}
  std::map<int, A *> &registerType() {
    static std::map<int, A *> map_instance;
    return map_instance;
  }
  A *create(int n) { return registerType()[n]; }
};
class B : A {
 public:
  B() { registerType()[1] = this; }
  void Foo() { std::cout << "I am B!n"; }
};
static B b0;
int main() {
  A *b1 = new A();
  b1 = b1->create(1);
  b1->Foo();
  return 0;
}

现在,如果我想将原始指针更改为唯一指针,我自然会得到一组错误(以下代码导致错误):

#include <iostream>
#include <map>
#include <memory>
class A {
 public:
  A() {}
  virtual void Foo() {}
  std::map<int, std::unique_ptr<A>> &registerType() {
    static std::map<int, std::unique_ptr<A>> map_instance;
    return map_instance;
  }
  std::unique_ptr<A> create(int n) { return registerType()[n]; }
};
class B : A {
 public:
  B() { registerType()[1](this); }
  void Foo() { std::cout << "I am B too!n"; }
};
static B b0;
int main() {
  std::unique_ptr<A> b1(new A());
  b1 = b1->create(1);
  b1->Foo();
  return 0;
}

错误是:

In member function 'std::unique_ptr<A> A::create(int)':
use of deleted function 'std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = A; _Dp = std::default_delete<A>]'
   std::unique_ptr<A> create(int n) { return registerType()[n]; }
In constructor 'B::B()':
no match for call to '(std::map<int, std::unique_ptr<A> >::mapped_type {aka std::unique_ptr<A>}) (B* const)'
   B() { registerType()[1](this); }
                               ^

所以我想知道:

  1. 独特的指针是否打算用于像我这样的情况?(我认为答案应该是肯定的!
  2. 我需要将this作为unique_ptr类型传递给registerType方法。如何将指向当前实例的指针(this关键字)的所有权传递给unique_ptr?(如果可能或打算可能。
  3. 如果在这里使用独特的指针是一种很好的做法,我应该如何实现它?

首先,如果有人想要实现工厂模式,使用原始指针实现的可接受方法如下:

#include <iostream>
#include <map>
class A;
class A_Factory {
 public:
  A_Factory() {}
  virtual A *create() = 0;
};
class A {
 public:
  A() {}
  static void registerType(int n, A_Factory *factory) {
    get_factory_instance()[n] = factory;
  }
  static A *create(int n) {
    A *A_instance = get_factory_instance()[n]->create();
    return A_instance;
  }
  virtual void setMyID(int n) {}
  virtual void I_am() { std::cout << "I am An"; }
  virtual ~A() {}
 protected:
  int MyID;
  static std::map<int, A_Factory *> &get_factory_instance() {
    static std::map<int, A_Factory *> map_instance;
    return map_instance;
  }
};
class B : public A {
 public:
  B() {}
  void Foo() {}
  void I_am() { std::cout << "I am B " << MyID << "n"; }
  void setMyID(int n) { MyID = n; }
  ~B() {}
 private:
};
class B_Factory : public A_Factory {
 public:
  B_Factory() { A::registerType(1, this); }
  A *create() { return new B(); }
};
static B_Factory b0_factory;
void caller() {}
int main() {
  A *b1 = A::create(1);
  A *b2 = A::create(1);
  b1->setMyID(10);
  b2->setMyID(20);
  b1->I_am();
  b2->I_am();
  delete b1;
  delete b2;
  return 0;
}

A 是基类,B 是派生类。如果我们1传递给A::create(int n),将生成一个类型为 B 的对象。内存是手动管理的,不会有内存泄漏。

关于帖子中的问题:

  1. 是的。unique_ptr很棒;只要有可能,就用它们!
  2. 根据问题中提出的设计,传递this的所有权在某种程度上是必要的。我想不出一种方法来传递this的所有权.有了答案中提出的设计,没有必要传递this的所有权。
  3. 在上述工厂模式中实现unique_ptr,如下所示:
#include <iostream>
#include <map>
#include <memory>
 class A;
 class A_Factory {
 public:
  A_Factory() {}
  virtual std::unique_ptr<A> create_unique() = 0;
};
 class A {
 public:
  A() {}
  static void registerType(int n, A_Factory *factory) {
    get_factory_instance()[n] = factory;
  }
  static std::unique_ptr<A> create_unique(int n) {
    std::unique_ptr<A> A_instance =
        std::move(get_factory_instance()[n]->create_unique());
    return A_instance;
  }
  virtual void setMyID(int n) {}
  virtual void I_am() { std::cout << "I am An"; }
  virtual ~A() {}
 protected:
  int MyID;
  static std::map<int, A_Factory *> &get_factory_instance() {
    static std::map<int, A_Factory *> map_instance;
    return map_instance;
  }
};
 class B : public A {
 public:
  B() {}
  void Foo() {}
  void I_am() { std::cout << "I am B " << MyID << "n"; }
  void setMyID(int n) { MyID = n; }
  ~B() {}
 private:
};
 class B_Factory : public A_Factory {
 public:
  B_Factory() { A::registerType(1, this); }
  std::unique_ptr<A> create_unique() {
    std::unique_ptr<A> ptr_to_B(new B);
    return ptr_to_B;
  }
};
 static B_Factory b0_factory;
 void caller() {}
 int main() {
  std::unique_ptr<A> b1 = std::move(A::create_unique(1));
  std::unique_ptr<A> b2 = std::move(A::create_unique(1));
  b1->setMyID(10);
  b2->setMyID(20);
  b1->I_am();
  b2->I_am();
  return 0;
}

如您所见,不需要手动内存管理,内存管理由unique_ptr处理。

相关内容

  • 没有找到相关文章

最新更新