gpt4 book ai didi

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

转载 作者:太空狗 更新时间:2023-10-29 20:58:36 27 4
gpt4 key购买 nike

我有一个旧的 C++ 工厂实现,我想在其中使用唯一指针而不是原始指针。我的代码的一个最小示例如下。我有一个基类 A 和一个派生类 B。在 main() 中,我将 1 传递给 A 中的 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 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 处理。

关于c++ - 在 C++ 中使用 unique_ptr 的工厂模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27282453/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com