所以我有一个C ++函数,我将指针传递给基类,如:
void DoStuffAndAssignPtr(MyBase* ptr)
{
MyBase* p;
//do stuff
if (stuff was awesome) p = new MyAwesome();
else p = new MyBase();
//vftable of p before the return is MyAwesome
(*ptr) = (*p);
}
现在我们需要调用'MyAwesome'和'MyBase'实现不同的虚拟方法。但是,在检查返回值时,如下所示:
void mainly()
{
MyBase* passMe = new MyBase();
DoStuffAndAssignPtr(passMe);
//now passMe is always being returned with MyBase's vftable
}
我们可以看到'passMe'始终是'MyBase'(就VSf中调试时vftable所示)。任何人都可以提供任何关于为什么会发生这种情况的指导,以及我如何确保'passMe'将调用虚拟方法的'MyAwesome'实现?
答案 0 :(得分:3)
问题在于使用(*ptr)=(*p)
。您应该使用ptr=p
。
只有指针和引用具有多态性。当您使用取消引用(星号*)时,您将失去此属性,并且只有基本部分从p
复制到ptr
。这是因为ptr
只有那部分信息的空间。
答案 1 :(得分:3)
你有对象切片问题,下面的语句切片MyAwesome对象为MyBase:
(*ptr) = (*p)
您只将MyBase*
传递给DoStuffAndAssignPtr并尝试分配一个新指针,该指针只会覆盖函数参数的副本。您需要传递指针的引用。
void DoStuffAndAssignPtr(MyBase*& ptr);
^^^
此外,由于新的外部DoStuffAndAssignPtr已经分配了passMe,因此您在DoStuffAndAssignPtr中为ptr创建了另一个元素,这将导致内存泄漏。
更好的解决方案是:
MyBase* MakeAClass()
{
if (stuff was awesome)
{
return new MyAwesome();
}
return new MyBase();
}
int main()
{
MyBase* passMe = MakeBase()
}