簡體   English   中英

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

[英]Factory pattern using unique_ptr in c++

我在c ++中有一個舊的工廠實現,我想在其中使用唯一指針而不是原始指針。 我的代碼的最小示例如下。 我有一個基類A和一個派生類B main() ,我將1傳遞給Acreate方法, 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 A\n"; }
  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 A\n"; }
  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處理。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM