获取对返回对象的引用
C++ obtaining a reference to a returned object
我需要通过引用抓取一个对象,我过去是这样做的:
MyObject& obj = FactoryThatGivesAnObject();
obj.MethodThatModifieObj();
不,我需要基于一个条件:
MyObject obj;
// Need obj to be a reference to the returned values below
if( foo )
obj = FactoryThatGivesAnObject();
else
obj = OtherFactoryThatGivesAnObject();
obj.MethodThatModifiesObj();
我如何在第二个例子中让obj成为引用?
与指针不同,引用只能设置一次。这在很多时候都是一个有用的功能,但这是一个令人沮丧的方面。您只需要设置一次引用,但可能是不同的内容。
你有两个选择。
1)使用三元操作符这通常是最简单的,如果您只处理两个工厂,并使用一个简单的布尔值来决定使用哪个:
MyObject& obj = ( foo
? FactoryThatGivesAnObject();
: OtherFactoryThatGivesAnObject() );
但是,如果foo
更复杂,或者如果您有多个出厂选项,则下一个选项可能更简洁。
MyObject& get_an_object(const int state) // or whatever parameters you need
{
switch(state)
{
case USE_LEGACY_FACTORY: return FactoryThatGivesAnObject();
case USE_FOO_FACTORY: return OtherFactoryThatGivesAnObject();
case DO_SOMETHING_ELSE: return YetAnotherObjectFactory();
}
throw std::runtime_error("Bad Factory Selector");
}
// usage is simpler now
MyObject& obj = get_an_object(foo);
注意,你可能需要传递几个参数给你的工厂方法:
- 选择标准。您的示例只是
foo
—一个简单的布尔值。随着业务的增长,您可能需要额外的标准来帮助确定使用哪个工厂。 - 工厂对象。你可能有工厂对象而不是工厂方法,在这种情况下,你需要将对那些对象的引用传递到你的方法中。
一种解决方案是使用三元操作符:
obj = foo ? FactoryThatGivesAnObject() : OtherFactoryThatGivesAnObject();
也可以使用指针:
MyObject* pobj;
if( foo )
pobj = &FactoryThatGivesAnObject();
else
pobj = &OtherFactoryThatGivesAnObject();
你的第一行是阴暗的:
MyObject& obj = FactoryThatGivesAnObject();
这是怎么回事?工厂方法不能返回对临时对象的引用,因此它能返回的唯一合理的引用是对动态创建的对象的引用——但是现在谁对这个对象负责呢?
(除非您只是返回对现有对象的引用,否则就是。但我假设你的工厂真的在创造新的对象。
这段代码是内存泄漏的车祸;我看不出有什么办法能写出这样合理的东西。一个更好的方法是在一个负责任的容器中返回新创建的对象,例如shared_ptr
或unique_ptr
:
#include <memory>
std::unique_ptr<MyObject> FactoryFunction()
{
return std::unique_ptr<MyObject>(new MyObject(3,5,7));
}
这样,如果没有人拿起工厂产品,或者发生异常,动态分配的对象将被正确处理。
这也使得根据条件赋值不同的指针变得很简单:
std::unique_ptr<MyObject> x;
if (...) { x = Factory1(); }
else if (...) { x = Factory2(a,b); }
else { x = Factory3(argc, argv); }
我如何在第二个例子中让obj成为引用?
你不能。引用是别名;您只能通过将它们指向某个对象来创建它们,并且一旦指向了它们,它们就不能被重新分配。
你可能最好在这里使用std::auto_ptr
或std::unique_ptr
之类的东西。注意,您的工厂需要返回auto/unique_ptr。如果您的工厂返回一个引用,我怀疑您可能不小心返回了对未命名临时(未定义行为)的引用,但如果没有看到工厂的代码,则很难判断。
这里有一个解决方案,它在技术上不是工厂,但解决了同样的问题——在更改参数时提供新对象:
struct A
{
int a;
float x;
int c;
};
class ObjectCollection
{
public:
ObjectCollection() { m_a.c = 10; }
A &get_obj_a(int a, float x)
{
m_a.a = a;
m_a.x = x;
return m_a;
}
private:
A m_a;
};
这个版本的优点是它没有传递对象的所有权,但是你仍然可以用它创建不同类型的对象。虽然两次调用get_obj_a()会导致问题,但只有在需要对象之前立即调用get_obj_a()才有效。现在可以将if语句放入工厂函数中。还有另一种方法:
class DerivedFactory
{
public:
DerivedFactory(ObjectCollection1 &c, ObjectCollection2 &c2) : c(c),c2(c2) { }
Base &get_obj_a_or_b(bool b) {
if (b) return c.get_obj_a(10,11.0);
else return c2.get_obj_b(20.0,13.0);
}
private:
ObjectCollection1 &c;
ObjectCollection2 &c2;
};
- 引用对象成员函数的成员函数
- 从 Base 引用对象调用派生类的成员
- 转换引用对象的边界框?
- 现代编译器会优化只引用对象子集的局部变量吗
- l值引用对象上的Constexpr成员函数:Clang和gcc不同意
- 将 const 类型引用对象注册为类成员对象C++
- Boost Intervocess:通过迭代通过从结构引用对象的映射进行迭代时
- 无法用2D矢量成员引用对象
- 在由引用对象传递中访问由引用对象传递的变量
- 如何使用QString引用对象名称
- 使用自动迭代器引用对象
- C++ 在另一个对象中引用对象的当前状态
- 使用共享对象和引用对象进行引用计数
- 未显式引用对象的全局对象构造函数在最终二进制文件 - LD 中被丢弃
- 引用对象的动态类型何时可以更改
- 引用对象内部的指针
- C++从全局静态函数中引用对象
- C++如何仅在没有其他人直接或间接引用对象指针时删除该指针
- 如何使用C++引用对象
- 为什么引用对象仅保存特定类型的引用