引用指针和 C++ 多态性
Posted
技术标签:
【中文标题】引用指针和 C++ 多态性【英文标题】:Reference to pointers and C++ polymorphism 【发布时间】:2009-05-22 17:17:30 【问题描述】:有谁知道为什么这会导致编译器错误?我试过 VS 2005 和 Codewarrior:
class Parent
protected:
int m_Var;
public:
Parent() : m_Var(0)
virtual ~Parent()
void PubFunc();
;
class Child : public Parent
protected:
bool m_Bool;
public:
Child() : m_Bool(false)
virtual ~Child()
void ChildFunc();
;
void RemoveObj(Parent *& ppObj)
delete ppObj;
ppObj = 0;
int main()
Parent* pPObj = 0;
Child* pCObj = 0;
pPObj = new Parent();
pCObj = new Child();
RemoveObj(pPObj);
RemoveObj(pCObj);
return 1;
视觉工作室说:
refptr.cpp(33):错误 C2664: “RemoveObj”:无法转换参数 1 从“子 *”到“父 *&”
谢谢
【问题讨论】:
【参考方案1】:RemoveObj 的 ppObj
参数是对 Parent* 的引用。如果RemoveObj()
方法将指针替换为指向新Parent
对象的指针怎么办?当方法返回您的 pCObj
Child*
将不再指向 Child
对象。
【讨论】:
【参考方案2】:来自 C++ 标准 (1998)
除非在上下文中 用户自定义初始化 转换 (13.3.1.4, 13.3.1.5), a 格式良好的隐式转换 序列是以下之一 形式:——标准转换 序列(13.3.3.1.1),-用户 定义...
13.3.3.1.1
每个转化最多一次 类别允许在单个 标准转换顺序
所以 c++ 不能连续两次隐式转换:从指针到指针,然后再从指针。
为了解决这个问题,考虑这样的 RemoveObj 声明
void RemoveObj(Parent ** ppObj)
你会看到这个错误
error: invalid conversion from 'Child**' to 'Parent**'
你必须像这样使用显式转换
RemoveObj((Parent**)&pCObj);
RemoveObj((Parent*&)&pCObj);
或者不得不改变
void RemoveObj(Parent *& ppObj)
到
void RemoveObj(Parent * ppObj)
或到
template <typename T>
void RemoveObj(T *& pObj)
delete pObj;
pObj = 0;
【讨论】:
这并不能回答为什么它是编译器错误,但它应该被更改为。对指针的引用对于执行该方法正在执行的操作不是必需的。 我已经添加了对标准的引用。 通过编辑,这绝对是您为什么会遇到编译器错误的答案。根据@MykolaGolubyev 指出的标准部分,您正在尝试进行两步转换,这是非法的。不幸的是,reinterpret_cast
是解决这个问题的最实用的方法。【参考方案3】:
ppobj 是指针的引用。 *ppobj 取消引用变量指向的内容,因此您可以获取变量指针。
由于取消引用的类型不正确,您会看到错误。
【讨论】:
【参考方案4】:指向引用的指针允许指针值在函数中改变。正如Michael Burr 所指出的,可能会分配不正确的类引用并返回它。想象一下你的整个程序错误地使用 *pchickens 作为 *peggs :)
我认为值得添加(尽管没有明确您的要求): 我对多态实现的偏好是将常用函数作为方法移动到内部。如果它们都共享一个函数,只需将其添加到基类中即可。
那么无论哪种方式,您都可以简单地调用 Foo->Bar() 并达到预期的效果。但是对于您给出的具体实现示例,只需 delete Foo 将调用适当的析构函数。
【讨论】:
【参考方案5】:这不是权威,但我认为问题在于 C++ 类的多态性并没有扩展到它们的指针;您期望在这里完成的是将Child *
转换为Parent *
;虽然您可以将 Child
转换为 Parent
,但您不能将指针 reference 转换。也就是说,类是多态的,但指向类的指针在作为引用时不是。这是迈克尔·伯尔(Michael Burr)在上面给出的原因; Child *
暗示了某种Parent *
没有的内存结构。
【讨论】:
指针之间的转换是可能的。但是,转换会临时返回一个右值。这就是它不能传递给非常量引用的原因。 问题出在参考,而不是指针。您可以互换地传递指针,但不能传递对不同类型指针的引用。 我认为您在谈论将左值转换为左值 w.r.t Child* 到 Parent*。你是对的,这样的转换是不可能的。但是您的帖子听起来像是在暗示 Child* to Parent* 是不允许的(事实并非如此)。没有投反对票,只是帮助你弄清楚他们为什么会反对你。 (如果他们只告诉你......) @litb:感谢您对解释的澄清;编辑使其更清晰。 可以做这个实验:void f(Parent * const& p);你可以用 f(pChild) 来调用它;因为隐式指针转换为 Parent* 的结果可以绑定到参数 p:它是一个非常量引用。由于我们不是在此处操作“多态”(我们不是说“参数 Child* 指针是参数 Parent* 指针”)而是在副本上操作,因此可以正常工作。我相信这就是你的意思。以上是关于引用指针和 C++ 多态性的主要内容,如果未能解决你的问题,请参考以下文章