Why does C ++ behave like this?

#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 an unnecessary value.

It should appear to be pointing to an object of type B and incrementing it by sizof(B) .

Why is this not happening?

+4
source share
7 answers

He can only know this at runtime. Imagine that has changed a bit.

 A* a; if(runtimevalue) a = new A[10]; else a = new B[10]; 

But that will not happen. C ++ emphasizes speed, but basically it turns it into a language that ensures the safety of operations. There are Java, C # and others that already solve this problem.

Kernel and device driver developers do not want to work with smart language. They just want everything to work fast.

Take a look at the common undefined behavior in C ++ for all the things that need to be β€œfixed”. It will no longer be C ++!

+7
source

No, this should not be. The declared type pA is A* , so it increases by sizeof(A) , which indicates that it points to the middle of the first B in the array.

+19
source

The reason it is fragile is because you are doing everything you can to protect you. While you are not experienced enough to find out why these problems arise and how to avoid them, you should:

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

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

Change As for why you see your behavior, it's pretty simple: pointer arithmetic is defined in terms of a static type, not a dynamic type. This means that it is entirely based on the type of pointer that you defined for the pointer, not what it points to. If you say that you point to A, but then point it to B, arithmetic will still perform as if it points to A, as you said.

+11
source

Pointer a points to an object with static type a and dynamic type B Pointer arithmetic in C ++ works in terms of a static type. So, in terms of pointer arithmetic, a points to an object of type a .

+3
source

You increase the variable a , which is the locally declared pointer of objects A. This is the same as saying a=a+sizeof(A) .

Since sizeof (B)> sizeof (A), you end up pointing to the middle of the first object. When C ++ adds the appropriate offset, it will finish reading the field c first object B. This happens as a single memory containing garbage.

+1
source

objects do not have a record of how and how big they are, it's just allocated memory. The only way the compiler knows how to process an object in pointer memory is by looking at the type of pointer. Therefore, based on the A * pointer, it will only accept the sizeof (A) object.

+1
source

For compatibility reasons, C arrays degrade pointers. Type B[10] can degrade to B* , and inheritance means that assigning a pointer to B variable of type A* permissible.

Then you increment the value of this pointer, which adds size A to its address.

However, your assumption that pointer increment is a valid operation if the pointer does not point to an array of pointer type elements is incorrect.

If you try to combine the C ++ parts that are there, so it behaves like C with the more strongly typed OO functions, the looser input in the C parts affects the stronger typing in the C ++ parts. It’s best to keep them separate, or at least document the expected behavior.

+1
source

Source: https://habr.com/ru/post/1310283/


All Articles