【问题标题】:Is there a C++ idiom for this ugly constructor/factory?这个丑陋的构造函数/工厂有一个 C++ 习惯用法吗?
【发布时间】:2015-08-28 19:00:00
【问题描述】:

我有一些看起来像这样的代码:

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 对象的单一“有福”的方式,但we cannot make the Widget constructor private because Widget::make is implemented in terms of make_unique

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

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

这一切都可以正常工作,没有工厂功能。

我遇到的问题是,我相信我们需要 v8::HandleScope 来围绕 create_v8_object() 内的所有 v8::Local&lt;T&gt;s 的构造,这是从构造函数的成员初始化器列表中调用的。我们需要一种方法在执行成员初始化器之前创建HandleScope,然后在构造函数结束时将其销毁。

我正在寻找一种方法以最大限度地提高代码清晰度来解决此问题。 (例如,我可以将成员 handleScope_ 添加到类中,并确保其成员初始化器是列表中的第一个(嗯,第二个,在 isolate_ 之后);但这会使类的大小膨胀我不知道如何在构造函数的末尾清理它。

我还考虑将HandleScopeWidget::make 移到Widget::create_v8_object(),在那里它将成为EscapableHandleScope,我们将return scope.Escape(gadget)。但是,如果我有很多 create_v8_object 调用,所有这些 HandleScopes 是否会造成性能损失,或者有任何其他不良影响?

【问题讨论】:

    标签: c++ factory v8 c++14


    【解决方案1】:

    委托构造函数怎么样?

    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} {}
    };
    

    【讨论】:

    • @Quuxplusone 你更喜欢委托构造函数吗?
    • 嗯,我更喜欢委托构造函数。这似乎是一个合理的解决方案。 在实践中我有一个小问题,因为我想要与 GCC 4.6 兼容的东西(委托构造函数在 4.7 中出现);但是从语言的角度来看,是的,委托构造函数完美地解决了这个问题!
    猜你喜欢
    • 1970-01-01
    • 2019-02-01
    • 1970-01-01
    • 2012-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-11
    相关资源
    最近更新 更多