JnB*_*ymn 11 c++ polymorphism reference object-slicing
我有一个时间了解参考的魔鬼.请考虑以下代码:
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();
}
Run Code Online (Sandbox Code Playgroud)
结果是:"树皮树皮rawr rawr".
用Java的思维方式(显然已经破坏了我对C++的概念化),结果将是"树皮树皮树皮".我从前一个问题中了解到,这种差异是由切片引起的,我现在对切片的理解有了很好的理解.
但是,让我们说我想要一个返回Animal值的函数,它实际上是一个Dog.
更新:因为到目前为止每个人似乎都同意rFunc它是非法的,这带来了另一个相关的问题:
如果我传回指针,如果是这种情况,我如何与程序员沟通指针不是他们要删除的?或者,我如何传达指针在任何时候(来自同一个线程但是不同的函数)都要删除,以便调用函数不应该存储它,如果是这种情况.是通过评论进行沟通的唯一方法吗?这似乎很草率.
注意:所有这些都导致了我正在研究的模板化shared_pimpl概念的想法.希望我能学到足够的东西,在几天内发布一些相关信息.
1)如果你正在创建新对象,你永远不想返回一个引用(参见你自己对#3的评论.)你可以返回一个指针(可能用std::shared_ptr
或包裹std::auto_ptr
).(您也可以通过复制返回,但这与使用new
运算符不兼容;它也与多态性略有不兼容.)
2)rFunc
是错的.不要那样做.如果您曾经new
创建过该对象,则通过(可选地包装)指针返回它.
3)你不应该这样做.这就是指针的用途.
编辑(回复您的更新:)很难描绘您所描述的场景.一旦调用者调用其他(特定)方法,返回指针可能无效会更准确吗?
我建议不要使用这样的模型,但如果你绝对必须这样做,并且你必须在你的API中强制执行,那么你可能需要添加一个间接级别,甚至两个.示例:将实际对象包装在包含实际指针的引用计数对象中.null
删除实际对象时,引用计数对象的指针被设置为.这很难看.(可能有更好的方法,但它们可能仍然很难看.)