我在这里什么都听不懂。我希望如果我可以将狗指针传递给获取动物指针的函数,我也可以将 &dog 传递给一个将指针传递给动物指针的函数。
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;
}
我只是不明白,谁能解释一下为什么特定情况有效而其他情况无效的原因是什么?就像将狗的指针地址传递给动物**一样,那将是一个向上的投掷,不是吗?
可相互转换的指针类型是指向派生/基类型的对象的指针。"指向指针的指针"不能与其他类型相互转换(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*
类型的非常量引用,因此我们只能向它传递Animal*
类型的 gl值,animal
是,但dog
不是。
最后一个有效,它是合法的,因为
refToConstPtr(animal); // Works
refToConstPtr(dog); // Works. This is the only one that allows me to send Dog to Animal
const
X
的引用可以绑定到任何X
值类别,包括寿命延长的临时性。因为我们可以dog
转换为Animal*
.该转换将发生,并生成一个临时Animal*
,其生存期通过const
引用延长。