简体   繁体   English

无法将指针向上转换为指针参数

[英]Can't upcast pointer to pointer argument

I can't understand anything here. 我在这里什么都不懂。 I expected that if I can pass a dog pointer to function taking animal pointer, I could also pass the &dog to a function that takes a pointer to pointer of Animal. 我希望,如果我可以将dog指针传递给采用动物指针的函数,也可以将&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;
}

I just don't get it, can anyone explain what the reasons are for why particular cases work and others don't? 我只是不明白,有谁能解释为什么特定案例起作用而其他案例不起作用的原因是什么? Like passing the dog pointer address to the Animal**, that would be an upcast, wouldn't it? 就像将狗的指针地址传递给Animal **一样,这是一个错误,不是吗?

interconvertible pointer types are pointers to objects of a derived/base type. 互转换指针类型是指向派生/基本类型的对象的指针。 A "pointer to a pointer" isn't interconvertible with other types (with the exception of void* ). A“指针的指针”是不是相互转换的与其它类型的(具有除外void* )。 Same applies to references. 同样适用于参考文献。

This means that given any hierarchy below: 这意味着给定以下任何层次结构:

struct Animal{};
struct Dog : Animal{};

And the following variables: 和以下变量:

Dog* dptr;
Animal* aptr;

dptr can be converted to Animal* (even implicitly), likewise aptr can be converted to Dog* (but not implicitly). dptr可以转换为Animal* (甚至隐式),同样aptr可以转换为Dog* (但不能隐式)。 Because: up-casting in a class hierarchy is always legal, hence this will be done implicitly by ICS . 因为:在类层次结构中进行向上转换始终是合法的,因此这将由ICS隐式完成。 However, down-casting isn't always so, so its never done implicitly) 但是,向下转换并不总是这样,因此它从未隐式完成)

However: 然而:

Dog** ddptr;
Animal** aaptr;

ddptr cannot be implicitly converted to Animal** , likewise aptr cannot be converted to Dog** . ddptr不能隐式转换为Animal** ,同样aptr不能转换为Dog** Because, they are two different types with no hierarchical relationship. 因为,它们是两种没有层次关系的不同类型。




The above explanation explains why the pointer to pointer overloads fail. 上面的解释说明了为什么指针重载指针失败。 That said, let's deal with the reference type overloads. 也就是说,让我们处理引用类型的重载。 From your code, 根据您的代码,

refToPtr(animal); // Works
refToPtr(dog);      // A reference of type Animal*& (not const-qualified) cannot be initialized with a value of type Dog*

the second call doesn't work because non-const references of say X can only be bound to an exact glvalue object of X . 第二个调用不起作用,因为说X非常量引用只能绑定到X的确切glvalue对象。 Since refToPtr takes a non-const reference to a Animal* type, we can only pass it glvalues of Animal* type, which animal is, but dog isn't. 由于refToPtrAnimal*类型采用非常量引用,因此我们只能向其传递Animal*类型的glvalues,即animal是,而dog不是。

the last one works, and it's legal because 最后一个有效,这是合法的,因为

refToConstPtr(animal); // Works
refToConstPtr(dog);    // Works. This is the only one that allows me to send Dog to Animal

const references of say X can be bound to any value catagory of X , including temproaries whose lifetimes are extended. const发言权引用X可以绑定到任何值产品类别X ,包括temproaries其寿命延伸。 Since since we can convert dog to Animal* . 因为我们可以将dog转换为Animal* That conversion takes place and a temporary Animal* is produced whose lifetime is extended by the const reference. 进行该转换并生成一个临时的Animal* ,其寿命通过const引用延长。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM