[英]Factory pattern using unique_ptr in c++
我在c ++中有一個舊的工廠實現,我想在其中使用唯一指針而不是原始指針。 我的代碼的最小示例如下。 我有一個基類A
和一個派生類B
在main()
,我將1
傳遞給A
的create
方法, b1
的類型現在更改為B
#include <iostream>
#include <map>
class A {
public:
A() {}
virtual void Foo() {}
std::map<int, A *> ®isterType() {
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>> ®isterType() {
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); }
^
所以我想知道:
this
作為unique_ptr
類型傳遞給registerType
方法。 我如何將指向當前實例( this
關鍵字)的指針的所有權傳遞給unique_ptr
? (如果可能或有意。) 首先,如果有人想要實現工廠模式,使用原始指針執行此操作的可接受方式如下:
#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
類型的對象。 手動管理內存,不會發生內存泄漏。
關於帖子中的問題:
this
在某種程度上必要的。 我不能想辦法傳遞的所有權this
。 隨着在回答提出的設計,沒有必要通過所有權this
。 #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.