有没有一个C++习语来形容这个丑陋的构造函数/工厂

Is there a C++ idiom for this ugly constructor/factory?

本文关键字:构造函数 工厂 有一个 C++ 习语      更新时间:2023-10-16

我有一些代码如下所示:

class Widget {
  public:
    static std::unique_ptr<Widget> make(OtherArgs args);  // factory pattern
    Widget(v8::isolate&& isolate, OtherArgs args);
  private:
    v8::Local<v8::Object> Widget::create_v8_object()
    v8::isolate isolate_;
    v8::Local<v8::Object> gadget_;
};
std::unique_ptr<Widget> Widget::make(OtherArgs args)
{
    v8::isolate isol;
    v8::HandleScope scope(isol.get());
    return std::make_unique<Widget>(std::move(isol), args);
}
Widget::Widget(v8::isolate&& isol, OtherArgs args) :
    isolate_(std::move(isol)),
    context_(isolate_.get()),
    gadget_(isolate_.get(), create_v8_object())
{
}
v8::Local<v8::Object> Widget::create_v8_object()
{
    v8::Local<v8::ObjectTemplate> tmpl = v8::ObjectTemplate::New(isolate_.get());
    // ...
    v8::Local<v8::Object> gadget = v8::Local<v8::Object>::New(isolate_.get(), tmpl->NewInstance());
    // ...
    return gadget;
}
int main()
{
    auto widget = Widget::make(some_args);
    // ...
}

然而,三行Widget::make函数是丑陋的——它是创建Widget对象的唯一"幸运"方式,但我们不能使Widget构造函数私有,因为Widget::make是根据make_unique实现的。

然而,如果我们可以让Widget构造函数本身创建"祝福"对象,我们可以将main()更改为

int main()
{
    auto widget = std::make_unique<Widget>(some_args);
    // ...
}

这一切都只是工作,没有工厂功能。

我遇到的问题是,我认为我们需要围绕create_v8_object()中所有v8::Local<T>的构造的v8::HandleScope,它是从构造函数的成员初始值设定项列表中调用的。在执行成员初始化程序之前,我们需要一种方法来创建HandleScope,然后在构造函数结束时销毁它。

我正在寻找一种方法来解决这个问题,最大限度地提高代码的清晰度。(例如,我可以将成员handleScope_添加到类中,并确保其成员初始值设定项在列表中是第一个(好吧,第二个,在isolate_之后(;但这会扩大类的大小我不知道如何在构造函数结束时清理它。

我还想过将HandleScopeWidget::make向下移动到Widget::create_v8_object(),在那里它将变成EscapableHandleScope,我们将成为return scope.Escape(gadget)。但是,如果我有很多create_v8_object调用,那么所有这些HandleScopes会对性能造成影响,还是会产生任何其他不良影响?

委派构造函数怎么样?

class Widget {
private:
    Widget(v8::isolate && isol, v8::HandleScope scope, OtherArgs args) { /* ... */ }
    Widget(v8::isolate && isol, OtherArgs args) : Widget{std::move(isol), {isol.get()}, args} { }
public:
    Widget(OtherArgs args) : Widget{{}, args} {}
};