我试图通过将引用传递给指针而不是指向指针的指针来回答这里提到的问题,如下所示:
class Parent { }; class Child : public Parent { }; void RemoveObj(Parent*& pObj) { delete pObj; pObj = NULL; } int main() { Parent* pPObj = new Parent; Child* pCObj = new Child; pPObj = new Parent(); pCObj = new Child(); RemoveObj(pPObj); RemoveObj(pCObj); // This is line 32 return 1; }
但是这会在第32行产生以下编译器错误:
错误C2664:'RemoveObj':无法将参数1从'Child*'转换为'Parent*&'
我同意不允许从Child**转换为Parent**.但为什么这种转换也不允许?
类型的对象Child*
不能绑定到a Parent*&
,原因与a Child**
无法转换为a的原因完全相同Parent**
.允许它允许程序员(有意或无意)在没有演员表的情况下打破类型安全.
class Animal {}; class DangerousShark : public Animal {}; class CuteKitten : public Animal {}; void f(Animal*& animalPtrRef, Animal* anotherAnimalPtr) { animalPtrRef = anotherAnimalPtr; } void g() { DangerousShark myPet; CuteKitten* harmlessPetPtr; f(harmlessPetPtr, &myPet); // Fortunately, an illegal function call. }
编辑
我认为由于"转换"和"转换"这两个词的使用松散,引起了一些混乱.
与可以重新分配的对象不同,引用不能被反弹,因此在我们提到转换的引用的上下文中,我们只关心初始化新引用.
引用总是绑定到一个对象,并且从OP的问题很明显,他的目标是获得一个直接绑定到现有对象的引用.仅当用于初始化引用的对象与引用类型引用兼容时,才允许这样做.本质上,这只是在类型相同的情况下,或者对象的类型是从引用的类型派生的,并且引用类型至少与初始化对象一样是cv限定的.特别是,无论指向类型的关系如何,指向不同类型的指针都不是引用兼容的.
在其他情况下,可以使用可以转换为引用类型的内容来初始化引用.但是,在这些情况下,引用必须是const而不是volatile,转换将创建一个临时引用,并且引用将绑定到此临时对象而不是原始对象.正如所指出的,这不适合OP的激励示例的要求.
总之,a Child
可以直接绑定到a Parent&
但Child*
不能直接绑定到a Parent*&
.A Parent* const&
可以用a初始化Child*
,但引用实际上将绑定到Parent*
从对象复制初始化的临时Child*
对象.