我很难理解引用文献。考虑以下代码:
class Animal
{
public:
virtual void makeSound() {cout << "rawr" << endl;}
};
class Dog : public Animal
{
public:
virtual void makeSound() {cout << "bark" << endl;}
};
Animal* pFunc()
{
return new Dog();
}
Animal& rFunc()
{
return *(new Dog());
}
Animal vFunc()
{
return Dog();
}
int main()
{
Animal* p = pFunc();
p->makeSound();
Animal& r1 = rFunc();
r1.makeSound();
Animal r2 = rFunc();
r2.makeSound();
Animal v = vFunc();
v.makeSound();
}
结果是:“bark bark rawr rawr”。
以 Java 的思维方式(这显然破坏了我对 C++ 的概念化),结果将是“bark bark bark bark”。我从我的 previous question 了解到这种差异是由于切片造成的,我现在对切片是什么有了很好的理解。
但是假设我想要一个返回真正是狗的 Animal 值的函数。
- 我是否正确理解我能得到的最接近的是引用?
- 此外,使用 rFunc 接口(interface)的人是否有义务查看返回的引用是否分配了一个 Animal&? (或以其他方式故意将引用分配给 Animal,它通过切片丢弃多态性。)
- 我到底应该如何返回对新生成的对象的引用而不做我上面在 rFunc 中做的愚蠢的事情? (至少我听说这是愚蠢的。)
更新:因为到目前为止每个人似乎都同意 rFunc 是非法的,这会带来另一个相关问题:
如果我传回一个指针,如果是这种情况,我如何与程序员沟通该指针不是他们要删除的指针?或者我如何传达指针随时可能被删除(从同一个线程但不同的函数),以便调用函数不应该存储它,如果是这种情况。是通过评论传达这一点的唯一方法吗?这看起来很草率。
注意:所有这些都导致了我正在研究的模板化 shared_pimpl 概念的想法。希望我能在几天内学到足够的东西来发布一些相关的东西。
最佳答案
1) 如果您正在创建新对象,您永远不想返回一个引用(请参阅您自己对 #3 的评论。)您可以返回一个指针(可能由 std::shared_ptr
包装或 std::auto_ptr
)。 (您也可以通过复制返回,但这与使用 new
运算符不兼容;它也与多态性略微不兼容。)
2) rFunc
是错误的。不要那样做。如果您使用 new
创建对象,则通过(可选包装的)指针返回它。
3) 你不应该这样做。这就是指针的作用。
编辑(响应您的更新:)很难想象您所描述的场景。一旦调用者调用其他(特定)方法,返回的指针可能无效会更准确吗?
我建议不要使用这样的模型,但如果您绝对必须这样做,并且必须在您的 API 中强制执行此操作,那么您可能需要添加一个间接级别,甚至两个。示例:将真实对象包装在包含真实指针的引用计数对象中。当实际对象被删除时,引用计数对象的指针设置为 null
。这太丑了。 (可能有更好的方法,但它们可能仍然很丑。)
关于c++ - 学习 C++ : returning references AND getting around slicing,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4405634/