I have the following class:
class BritneySpears
{
public:
int getValue() { return m_value; };
private:
int m_value;
};
Which is an external library (that I can’t change). I obviously can’t change the value of m_value, only read it. Even deriving from BritneySpears won’t work.
What if I define the following class:
class AshtonKutcher
{
public:
int getValue() { return m_value; };
public:
int m_value;
};
And then do:
BritneySpears b;
// Here comes the ugly hack
AshtonKutcher* a = reinterpret_cast<AshtonKutcher*>(&b);
a->m_value = 17;
// Print out the value
std::cout << b.getValue() << std::endl;
I know this is bad practice. But just out of curiosity: is this guaranteed to work? Is it defined behaviour?
Bonus question: Have you ever had to use such an ugly hack?
This is undefined behaviour. The members within each access-qualifier section are guaranteed to be laid out in the order they appear, but there is no such guarantee between acccess qualifiers. For instance, if the compiler chooses to place all private members before all public members, the above two classes will have a different layout.
Edit: Revisiting this old answer, I realized that I missed a rather obvious point: the struct definitions have exactly one data member each. The order of member functions is irrelevant, since they don’t contribute to the class’s layout. You might well find that both data members are guaranteed to be in the same place, though I don’t know the standard well enough to say for sure.
But! You cannot dereference the result of
reinterpret_casting between unrelated types. It’s still UB. At least, that’s my reading of http://en.cppreference.com/w/cpp/language/reinterpret_cast, which is a gnarly read indeed.