2

I do not understand the two lines mentioned below in the code that I have provided here. Why I need to use int*? How I am accessing the private variable? I am not sure what I am doing with these two lines. Please explain in detail.

Problematic lines:

int *p = (int *) &s;  
*p=10;

Main Code:

#include <iostream>

using namespace std;

class sample {
private:
  int a;
public:
  void function () {
    a=5;
  }
  void printA () {
    cout<<"value is "<<a<<endl;
  }
};

int main () {
  sample s;
  s.function();
  s.printA();

  int *p = (int *) &s;
  *p=10;

  s.printA();
}
andy256
  • 2,821
  • 2
  • 13
  • 19
user3751012
  • 533
  • 1
  • 8
  • 20
  • you just simply can add there any virtual method and at VS and gcc "a" will not be changed. – Arkady Jun 24 '14 at 11:05

3 Answers3

5

Using (int*) there is a really really bad idea. You are using a class, that isn't an int, as an int. Which is bad.

You can't access private members, and you shouldn't, that's why they are private.

int *p = (int *) &s;  
*p=10;

This means, you have an object s, of type sample, and it has a data member int a;. What you wrote works, because a happens to be at the beginning of the class.

There are some cases where the layout of a class is guaranteed, you can read about it here:

Community
  • 1
  • 1
Zsolt
  • 582
  • 2
  • 5
2

First off, please never do this.

You're exploiting the memory layout of the class sample. The first member is an int and it resides at the start of the class' memory space.

Try adding another int before a and you'll see that a is not changed.

Rakib
  • 7,435
  • 7
  • 29
  • 45
AlexanderBrevig
  • 1,967
  • 12
  • 17
1

This code is trying to access the member a in class sample by breaking the encapsulation imposed by class with the help of pointer casting. It is not safe, coz it depends on the memory layout of class members.

The assumption is that, the member a will be at the starting position of a sample object, so taking the address of the object, and casting it to int* will make it possible to access the first int member.

This is working because a is indeed in the first position, but this is not guaranteed and will not work for other members due to padding/alignment and in case of inheritance hierarchy. This type of code is dangerous.

You should have accessors/mutators of private members if required, instead of writing this kind of code access them.

Rakib
  • 7,435
  • 7
  • 29
  • 45
  • "this is not guaranteed" - yes it is (since C++11), unless you change the class so it's no longer standard-layout. I agree that it's dangerous, since such a change would silently break the code; but you can (portably) depend on the layout of such a class if you really need to. – Mike Seymour Jun 24 '14 at 12:21