这个问题要求在C++中实现静态工厂方法的简洁方法,这个答案描述了一种明确的方法.返回值优化将使我们免于制作不必要的副本Object,从而使这种方式创建Object与直接调用构造函数一样高效.复制i到id私有构造函数内部的开销可以忽略不计,因为它很小int.
但是,当Object包含一个实例变量Foo(它需要复杂的初始化逻辑)而不是一个小的基本类型时,问题和答案不会涵盖更复杂的情况.假设我想Foo使用传递给的参数构造Object.使用构造函数的解决方案看起来像:
class Object {
Foo foo;
public:
Object(const FooArg& fooArg) {
// Create foo using fooArg here
foo = ...
}
}
Run Code Online (Sandbox Code Playgroud)
使用类似于引用答案的静态工厂方法的替代方案将是,因为在我看来:
class Object {
Foo foo;
explicit Object(const Foo& foo_):
foo(foo_)
{
}
public:
static Object FromFooArg(const FooArg& fooArg) {
// Create foo using fooArg here
Foo foo = ...
return Object(foo);
}
}
Run Code Online (Sandbox Code Playgroud)
这里,复制foo_到的开销foo不再可以忽略不计,因为它Foo可以是任意复杂的类.而且,据我所知(这里我可能是错误的C++ newbie),这段代码隐含地要求为其定义一个拷贝构造函数Foo.
在这种情况下,实现这种模式的同样干净但有效的方法是什么?
为了预测可能的问题,为什么这是相关的,我认为构造函数的逻辑比复制参数是一个反模式更复杂.我希望构造函数:
因此,我更喜欢将复杂的初始化逻辑放入静态方法中.此外,这种方法提供了额外的好处,例如,即使输入参数类型相同,也可以通过静态工厂方法名称进行重载,并且可以清楚地说明在方法名称内部正在进行的操作.
感谢移动构造函数,您可以:
class Object {
Foo foo;
explicit Object(Foo&& foo_) : foo(std::move(foo_)) {}
public:
static Object FromFooArg(const FooArg& fooArg) {
// Create foo using fooArg here
Foo foo = ...
return Object(std::move(foo));
}
};
Run Code Online (Sandbox Code Playgroud)
如果Foo不可移动,将其包装在智能指针中是可能的:
class Object {
std::unique_ptr<Foo> foo;
explicit Object(std::unique_ptr<Foo>&& foo_) : foo(std::move(foo_)) {}
public:
static Object FromFooArg(const FooArg& fooArg) {
// Create foo using fooArg here
std::unique_ptr<Foo> foo = ...
return Object(std::move(foo));
}
};
Run Code Online (Sandbox Code Playgroud)
直接从所需的参数初始化构造函数中的实例有什么问题?
class Object
{
Foo foo; // or const Foo foo, disallowing assignment
public:
explicit Object(FooCtorArgs const&fooArg,
const AdditionalData*data = nullptr)
: foo(fooArg) // construct instance foo directly from args
{
foo.post_construction(data); // optional; doesn't work with const foo
}
static Object FromFooArg(FooCtorArgs const&fooArg,
const AdditionalData*data = nullptr)
{
return Object{fooArg,data}; // copy avoided by return value optimization
}
};
Run Code Online (Sandbox Code Playgroud)
fooAFAICT,即使您需要调整后期施工,也无需复制/移动任何内容。
| 归档时间: |
|
| 查看次数: |
1597 次 |
| 最近记录: |