3

I was just going through some codes of C++. Where in I came across the concept of reinterpret_cast operator.

EDIT 1 :

I know that accessing private members of a class is not recommended. But in some situations we ought to go ahead and access them. I have just put forth this question to get my concepts clear.

In the example that I referred,the private member of the Class is accessed by simply creating a structure with the same variables and then later on modified by implementing reinterpret_cast operator.

I have understood the usage of reinterpret_cast operator,as in I know what it does,but I fail to understand how a structure could be used to modify the values of a private Class member.

Following is the source code which I referred:

Class:

class Student
{
public:
    explicit Student(float percent) // Cannot be used for conversion
    {
        static int nid;

        id = ++nid;
        score = percent;
    }

    int Id() const
    {
        return id;
    }

    float GetScore() const
    {
        return score;
    }

    void SetScore(float value)
    {
        score = value;
    }

    virtual ~Student(){}

private:
    int id;
    float score;
};

Structure used to access and modify private class members:

struct _Student
    {
        void* vptr;
        int id;
        float score;
    };

    _Student* bs3 = reinterpret_cast<_Student*>(bs2);
    bs3->id = 5;

Thank you.Please correct me if I'm wrong/I couldn't put forth my question in an appropriate manner.

Pavitar
  • 4,282
  • 10
  • 50
  • 82
  • Hm, maybe you could implement a `friend` class with a function to convert your object with the private members to a structure or data type with these private members exposed. This would make your code a bit cleaner and less evil :) – Arc Sep 29 '10 at 09:42
  • Yes.This question is just to get my fundamentals clear.I know its not recommended though.check edit 1. – Pavitar Sep 29 '10 at 09:49
  • I did see your disclaimer, but this is just plain evil (unless you can prove the opposite by explaining why you cannot solve it in a different way). – Arc Sep 29 '10 at 10:32

5 Answers5

3

$5.2.10/2 - "An expression of integral, enumeration, pointer, or pointer-to-member type can be explicitly converted to its own type; such a cast yields the value of its operand."

This means that pointers 'bs2' and 'bs3' are pointing to the same location

$9.2/16 - "Two standard-layout struct (Clause 9) types are layout-compatible if they have the same number of non-static data members and corresponding non-static data members (in declaration order) have layout-compatible types (3.9)."

This means that your class and struct are layout compatible.

$9/6-

A standard-layout class is a class that:

— has no non-static data members of type non-standard-layout class (or array of such types) or reference,

— has no virtual functions (10.3) and no virtual base classes (10.1),

— has the same access control (Clause 11) for all non-static data members,

— has no non-standard-layout base classes,

— either has no non-static data members in the most-derived class and at most one base class with non-static data members, or has no base classes with non-static data members, and

— has no base classes of the same type as the first non-static data member.108

Since your class has a virtual destructor, your class and struct are not standard layout classes.

However you have added a 'void *' data member to possibly take care of the 'vptr' (thereby possibly mimicking layout compatibility based on your particular compiler implementation)

In this case reinterpret_cast is used to interpret the class pointer (bs2) as a struct pointer (bs3). By default struct members are public. Since the return value of reinterpret cast points to the same memory (refer quote above) where class members are located, you can modify the struct members (which are the same as the original class members).

This is cheating. This is highly discouraged.! This is most likely going to lead to undefined behavior

Chubsdad
  • 24,777
  • 4
  • 73
  • 129
  • 2
    The struct and the class are NOT layout-compatible: The struct has a void*, the class hasn't. And no, the vtable pointer doesn't count, as the C++ standard doesn't mandate it. Bottomline: it might work on your current compiler, but the C++ standard doesn't guarantee it. – Sjoerd Sep 29 '10 at 10:13
  • @Sjoerd: Yes :), As soon as I submitted my revised update, I saw your comments. – Chubsdad Sep 29 '10 at 10:35
3

But in some situations we ought to go ahead and access them.

And what, pray, are these situations?

Other than design errors, I can’t see any. Accessing private members is a no-go. If you need the access, then provide it by legal means, i.e. either make the members more accessible or use friend modifiers to access them in a controlled way.

Violating the C++ type checking system equals game over: you cheat the compiler, don’t expect it to work with you. With this kind of undefined behaviour (i.e. not just platform dependent but forbidden for good reasons) you’re just inviting trouble in the form of very hard to track bugs.

tl;dr: Don’t. Ever.

Caveat: There is one exception: you have a library that you cannot access/modify the source code of, and you have no way of influencing its interface design. And additionally you can be sure (how?) that it won’t ever change. In this case the only solution may be to hack the library with such tricks.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
2

I think you should perhaps change the context of your question somewhat. If you realize you need to access a private variable in your class then you are facing a design problem that needs to be resolved instead of hacked around using an unsafe type conversion. Even if it is just hypothetical and for the sake of asking about reinterpret_cast here.

As for a use case of reinterpret_cast that makes sense I'd say inside a hash function:

unsigned short Hash( void *p ) {

unsigned int val = reinterpret_cast<unsigned int>( p );
return ( unsigned short )( val ^ (val >> 16));

}

Some links with useful info:

When should static_cast, dynamic_cast, const_cast and reinterpret_cast be used?

http://advancedcppwithexamples.blogspot.com/2010/02/reinterpretcast-in-c.html

http://www.linuxtopia.org/online_books/programming_books/thinking_in_c++/Chapter03_054.html

Community
  • 1
  • 1
gilligan
  • 488
  • 3
  • 15
1

But in some situations we ought to go ahead and access them.

If you have to access them in any situation, change its access specification.

Or better, make a public method that would accept a token(or some special permissions - to validate the caller), and return the requested value.

KMån
  • 9,896
  • 2
  • 31
  • 41
1

What you've got there is a horrible hack around encapsulation. If you really want to access private variables then you should be using the "friend" keyword. The reason the reinterpret_cast works is because you're interpretting the bytes of class Student as the struct _Student - which has it's variables declared as public by default. There are all manner of bad ways to access the private data, here's another one I can think of:

int* bs3 = reinterpret_cast<int*>(bs2);
++bs3;
*bs3 = 5;

Just don't do it would be my advice.

Mark Ingram
  • 71,849
  • 51
  • 176
  • 230