我有这样的事情:
struct D {
virtual void operator() {...};
}
struct D1 : public D {
virtual void operator() {...};
}
struct D2 : public D {
virtual void operator() {...};
}
void foo(D &d) {...};
所以这很好,很好地控制了我D的生命周期:
foo(D());
foo(D1());
foo(D2());
但是我在多个地方选择我的D变种,所以我想要一个简单的工厂:
const D& make_D()
{
// BAD, returning reference to temporary
if(is_tuesday())
return D1();
return D2();
}
我可以返回一个对象,而不是返回对临时的引用,然后切换到基类。或者,我可以从我的工厂返回一个指针,但客户端必须删除它。其他更复杂的解决方案也会给客户带来更多负担。
有没有办法写出像
这样的东西D& d = make_D();
foo(d);
(甚至foo(make_D())
)?目标是将复杂性包含在各种D定义和make_D()
中,以便像foo()
这样的函数和调用这些函数的函数不必担心它。
答案 0 :(得分:5)
通常的方法是返回指针或智能指针。
使用指针的缺点是让用户管理其内存。
如果你返回一个智能指针,这不再是一个问题。
const SmartPtr<D> make_D()
{
if(is_tuesday())
return SmartPtr(new D1());
return SmartPtr(new D2());
}
答案 1 :(得分:5)
不幸的是,这是不可能的。
通常,我所做的就是使用std::unique_ptr
(有时std::shared_ptr
,当无法使用std::unique_ptr
时):
typedef std::unique_ptr< D > Dptr;
Dptr make_D()
{
Dptr p( nulptr );
if(is_tuesday())
p.reset( new D1 );
else
p.reset( new D2 );
return p;
}
答案 2 :(得分:0)
首先,我不太清楚我的理解。您列出的代码不是 合法,不会编译。你确定它不是:
struct D
{
virtual void operator()() const { /* ... */ }
};
和
void foo( D const& d ) { /* ... */ }
调用,还是可变的? (大概不是,因为你没有通过任何 参数,你在使用后丢弃对象。)如果没有,那么你 可以简单地返回对静态实例的引用。这是通常的 我用的解决方案。否则,可以制作可复制对象 使用字母包络成语,表现多态,但它有点 工作,并且具有显着的运行时开销,因为它通常 需要克隆每个副本的实际对象。