C ++指针协方差

砂仁

我从未想到c ++具有指针协方差,因此可以像这样用腿射击自己:

struct Base
{
    Base() : a(5) {}
    int a;     
};

struct Child1 : public Base
{
    Child1() : b(7) {}
    int b;
    int bar() { return b;}
};

struct Child2 : public Base
{
    Child2(): c(8) {}
    int c;
};

int main()
{
    Child1 children1[2];

    Base * b = children1;

    Child2 child2;

    b[1] = child2; // <------- now the first element of Child1 array was assigned a value of type Child2

    std::cout << children1[0].bar() <<  children1[1].bar(); // prints 57 
}

这是不确定的行为吗?有什么方法可以阻止它,或者至少从编译器发出警告?

山姆·瓦尔沙夫奇克(Sam Varshavchik)

是的,这是未定义的行为。

而且不,目前,典型的C ++编译器不太可能在此处识别出需要诊断的内容。但是,C ++编译器每年都变得越来越聪明。谁知道从现在起几年后的事态...

但是,有一个小问题:

b[1] = child2; // <------- now the first element of Child1 array was assigned...

不,这不是第一个要素。这是第二个要素。b[0]将是第一个元素。此外,b它不是一个数组,而是一个指针。它是指向单个元素的指针。它不是指向两个元素数组的指针。

这就是未定义行为的来源。

它不是数组的原因是:

Base * b = children1;

children1衰减到一个Child1 *如果那是事情的结局,那么您可以说这b将是一个包含两个元素的数组的指针。

但这不是事情的结局。衰减的指针然后被强制转换为Base *您可以隐式地将指向子类的指针转换为指向超类的指针。但是(现在大胆地讲)您不能将指向子类数组的指针转换为超类数组。因此,b严格来说,它是指向单个元素的指针,并b[1]成为未定义的行为。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章