Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does C++ behave this way?

#include<stdio.h>

class A { public: int a;};

class B: public A {
    int c; 
    int d;
};

int main() {

    A* pA = new B[10];
    B* pB = new B[10];

    printf("\n%d", pA->a);
    pA++;
    printf("\n%d", pA->a);  // prints junk value

    printf("\n\n%d", pB->a);
    pB++;
    printf("\n%d", pB->a);
    return 0;
}

The second printf prints a junk value.

It should figure that it is pointing to an object of type B and increment by the sizof(B).

Why does that not happen?

like image 983
Lazer Avatar asked Nov 27 '22 22:11

Lazer


2 Answers

No it shouldn't. The declared type of pA is A*, so it is incremented by sizeof(A), which leaves it pointing to the middle of the first B in the array.

like image 157
Stephen C. Steel Avatar answered Nov 29 '22 11:11

Stephen C. Steel


The reason it's fragile is that you're side-stepping everything it does to try to keep you safe. Until you're sufficiently experienced to know why these problems are arising, and how to avoid them, you should:

  1. Forget that printf exists. Use std::cout instead.
  2. Forget that new exists. Use std::vector instead.

You should probably also read the C++ FAQ, and pay close attention to the part that says something to the effect that: "Even if an X is a Y, an array of X is not an array of Y."

Edit: As to why you're seeing the behavior you are, it's pretty simple: pointer arithmetic is defined in terms of the static type, not the dynamic type. That means it's based entirely on the type of pointee you defined for the pointer, NOT what it's pointing at. If you say it's pointing at an A, but then point it at a B, the arithmetic will still be done as if it was pointing at an A as you said it would.

like image 35
Jerry Coffin Avatar answered Nov 29 '22 13:11

Jerry Coffin