gpt4 book ai didi

c++ - 在派生类的对象创建期间使用 shared_from_this() 的两阶段构造

转载 作者:太空狗 更新时间:2023-10-29 23:02:24 26 4
gpt4 key购买 nike

我有一个基类继承自 enable_shared_from_this 的设置

class Object : public enable_shared_from_this<Object>
{ ... };

我继承自 enable_shared_from_this,因为我需要经常调用 shared_from_this()。在 Object 的某些派生中,我需要在构造函数中从 with 调用 shared_from_this(),这是无法完成的:

class Thing : public Object
{
public:
Thing() : Object(...)
{ doSomething(shared_from_this()); /* error */ }
};

因此,解决方法是分两阶段构建。

class Thing : public Object
{
public:
Thing() : Object(...) { }
void Init() { /* safe to call shared_from_this here */ }
};

创建 Thing 对象的有效方法是:

shared_ptr<Thing> thing = make_shared<Thing>();
thing->Init();

这不是很好并且容易出错,但至少它可以工作。但是,现在存在进一步继承的问题:

class Bling : public Thing
{
public:
Bling() : Thing(...) { ... }
void Init() { /* safe to call shared_from_this here */ }
};

// How do we create a Bling object?
shared_ptr<Bling> bling = make_shared<Bling>();
static_cast<Thing*>(bling.get())->Init(); // horrible
bling->Init();

// Maybe Bling::Init should look like:
// Bling::Init() { Thing::Init(); /* + other stuff */ }
// then we could do:
shared_ptr<Bling> bling = make_shared<Bling>();
bling->Init(); // etc

有没有更安全或更清洁的方法来做到这一点?例如,API 明智地使 Object、Thing 和 Bling 的构造函数成为私有(private)的并使用创建 shared_ptr 的静态 Init() 函数更不容易出错:

static shared_ptr<Bling> Bling::Init() {
auto bling = make_shared<Bling>();
Bling::init(bling);
return bling;
}

static void Bling::init(shared_ptr<Bling> bling) {
/* chain parent class init */
Thing::init(bling); // sig: Thing::init(shared_ptr<Thing>);

/* do init stuff */
}

// calls Object(), Thing(), Bling(),
// Object::init(), Thing::init(), Bling::init()
auto bling = Bling::Init();

基本上,我正在寻找实现对象创建的模式,以便我可以在创建期间对对象使用 shared_ptr。我需要允许基本继承。我想要建议的方法来考虑最终用户的易用性和开发人员的可维护性。

最佳答案

您可能不应该相信对象的用户最初总是将其保存在共享指针中这一事实。设计类以允许对象出现在堆栈和堆上。

如何解决这个问题取决于您如何处理 shared_from_this() 返回的指针。

我想到的一件事是对象在某个地方注册了自己——即在对象之外。在我看来,最好在从 Object 派生的数据类之外执行此操作。如果你有一个 Registry 类的注册表对象,将它变成一个工厂(按照 David Schwartz 的建议):

class Registry;

class Object
{
protected:
Object() = default;
friend Registry;
public:
// ...
};

class Thing : public Object
{
protected:
Thing() = default;
friend Registry;
public:
// ...
};

class Registry
{
vector<shared_ptr<Object>> store;
public:
shared_ptr<Thing> CreateThing()
{
shared_ptr<Thing> newThing = make_shared<Thing>();
newThing->init(); // If you like.
store.push_back(newThing);
return newThing;
}
shared_ptr<Bling> CreateBling();
// ...
};
  • 根本不需要 enable_shared_from_this
  • 更容易理解。
  • 职责明确。
  • 轻松更改,允许未注册的 ObjectThing 对象。 (划掉 protected 构造函数和 friend 声明。)

它可能已经很清楚了,但只是为了确定:我不赞成 enable_shared_from_this。它假设对象在调用 shared_from_this() 时由 shared_ptr 管理。如果不是这种情况,则“行为未定义”。如果至少它会是一个异常或 nullptr 将被返回...

当初始 shared_ptr 的创建和 shared_from_this() 的调用在代码中彼此接近时(无论那是什么意思),这样的假设是可以的。有人有这个用例吗?我不知道。

关于c++ - 在派生类的对象创建期间使用 shared_from_this() 的两阶段构造,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28712865/

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