我在这里无法理解任何事情。我期望如果我可以将狗指针传递给使用动物指针的函数,我也可以将& dog传递给一个带有指向Animal指针的函数。
struct Animal{};
struct Dog : Animal{};
void ptrToPtr(Animal** arg){}
void refToPtr(Animal*& arg){}
void refToConstPtr(Animal* const & arg){}
void ptrToConstPtr(Animal* const * arg){}
int main(void)
{
Dog* dog;
Animal* animal;
ptrToPtr(&animal); // Works
ptrToPtr(&dog); // Argument of type Dog** is incompatible with argument of type Animal**
refToPtr(animal); // Works
refToPtr(dog); // A reference of type Animal*& (not const-qualified) cannot be initialized with a value of type Dog*
ptrToConstPtr(&animal); // Works
ptrToConstPtr(&dog); // Argument of type Dog** is incompatible with paramater of type Animal* const*
refToConstPtr(animal); // Works
refToConstPtr(dog); // Works. This is the only one that allows me to send Dog to Animal
return 0;
}
我只是没有得到它,任何人都可以解释为什么特定案例有效的原因和其他人没有?就像将狗指针地址传递给动物**一样,这将是一个向上的,不会吗?
答案 0 :(得分:3)
可互换的指针类型是指向派生/基类型对象的指针。 “指针指针”与其他类型可互换(void*
除外)。同样适用于参考文献。
这意味着给定以下任何层次结构:
struct Animal{};
struct Dog : Animal{};
以下变量:
Dog* dptr;
Animal* aptr;
dptr
可以转换为Animal*
(甚至隐式),同样aptr
可以转换为Dog*
(但不能隐式)。 因为:在类层次结构中向上转换始终是合法的,因此这将由ICS隐式完成。然而,向下投射并不总是如此,所以它永远不会隐含地完成
然而:
Dog** ddptr;
Animal** aaptr;
ddptr
无法隐式转换为Animal**
,同样aptr
无法转换为Dog**
。因为,它们是两种不同的类型,没有层次关系。
上面的解释解释了指针指针重载指针失败的原因。 也就是说,让我们处理引用类型重载。从你的代码中,
refToPtr(animal); // Works
refToPtr(dog); // A reference of type Animal*& (not const-qualified) cannot be initialized with a value of type Dog*
第二个调用不起作用,因为说X
的非常量引用只能绑定到X
的完全 glvalue 对象。由于refToPtr
对Animal*
类型采用非const引用,因此我们只能传递Animal*
类型的glvalues,animal
是{,} {}} “T
最后一个有效,这是合法的,因为
dog
refToConstPtr(animal); // Works
refToConstPtr(dog); // Works. This is the only one that allows me to send Dog to Animal
对const
的引用可以绑定到X
的任何值类别,包括其生命周期延长的temproaries。由于我们可以将X
转换为dog
。进行转换并生成临时Animal*
,其生命周期由Animal*
引用扩展。