Question

Is it appropriate to access a class' private members by casting it to a void pointer and then to a struct?

I don't think I have permissions to modify the class that contains the data members that I need to access. I don't want to take a risk accessing the data members in an indirect way if it is not ethical.

EDIT: Had to edit this further... I am pretty sure the class wouldn't be modified, so it's ok to that extent... my only concern is, if the person who coded that class gets to know of this, it might not go down well with him :(.

Was it helpful?

Solution

"Never say never". I'm sure somewhere in the universe, there's a situation that will force you to have to do this...

But I certainly would cringe if I had to do it. You truly need get lots of opinions on your situation before pulling the trigger. Can you describe your specific situation and maybe we could see if it makes sense or what better alternatives might exist?

In response to comment/question-- Define "permissions" -- institutional permission? That sounds like not a programming problem, but something to talk to whoever is asserting said permission. Maybe this is more of a political issue than a technical one? Again, I think we need more specifics--even if it was somewhat about the politics of the situation. That may or may not be deemed out of scope for the website, however.

OTHER TIPS

Let's not consider ethics for a moment. Let's consider the standard.

What you are proposing to do is nonstandard. See section 9.2, clause 12 of the standard. "The order of allocation of nonstatic members separated by an access-specifier is unspecified." Therefore, if you have a class with private members, and a struct with no private members, the standard does not guarantee that the members will be in the same order.

Therefore, if your hack works, it works only by accident, that the compiler writers happened to do it that way. There is no guarantee that it will work on another compiler, a later version of the same compiler, or with different class layouts.

Not to mention that, if you don't have authority to modify the class (say, to provide a simple accessor function), you probably don't have authority to object if any implementation detail in the class changes. (One of the ideas behind public and private is to distinguish what is promised from what is freely changeable.) Therefore, the layout may change, or the member might come to mean something different, or be removed altogether.

Herb Sutter wrote a Guru of the Week column on this issue.

Oh, as far as the ethics go? If you really, really have to do something like this, and you can't get out of it, document it very carefully. If your coding standards have some sort of procedure to flag nonstandard behavior, use them. If not, be very careful to note it in a way it won't be overlooked when something goes wrong.

I'm not sure that "ethics" really come into it. It busts the heck out of encapsulation though.

EDIT: I would almost never accept this if I were performing a code review. You'd have to work really hard to convince me there's no way of designing around the need for this. It's possible you'd succeed, but there'd have to be major warnings all over the place, and rock hard unit tests to make sure that if anything changed to break it, you'd know quickly.

I've just added an entry to my blog that shows how it can be done in a completely conforming way. Here is an example on how you use it for the following class

struct A {
private:
  int member;
};

Just declare a tag name and instantiate a robber like the following example shows (my post shows the implementation of the robber). You can then access that member using a member pointer

struct Amem { typedef int type; };
template class rob<Amem, &A::member>;

int main() {
  A a;
  a.*result<Amem>::ptr = 42; // Doh!
}

But actually, this doesn't show that c++'s access rules aren't reliable. The language rules are designed to protect against accidental mistakes - if you try to rob data of an object, the language by-design does not take long ways to prevent you.


The above is a way to access private and protected members in a conforming way. This one is another way to access protected members in a Standard conforming way. The basic idea is to use a member pointer

std::deque<int> &getAdapted(std::stack<int> &s) {
    struct voyeur : stack<int> 
    { using stack<int>::c; };
    return s.*(&voyeur::c);
}

int main() {
    std::stack<int> s;
    std::deque<int> &adapted = getAdapted(s);
    output(adapted); // print the stack...
}

No casting or type punning involved. It takes a pointer to a protected member of std::stack<int> through a class derived from it where that member name is public, so the compiler allows this. Then it uses it on a std::stack<int> object, which is allowed too.

No. What you are doing is Pure Evil.

I have had this happen to me since there was a very crappy source control system in place where for old versions of the application making changes to header files was pretty much impossible.

If some cases you just need to do a hack.

In the source file from which you need to access the private data member you can put in this as a first line:

#define private public
#define protected public

and access anything you want.

If you feel the urge to do this, forget casting - just modify the class declaration in the header file:

class A {
  private:
    int x;
};

change that to:

class A {
  public:
    int x;
};

and you are good to go. Well, perhaps "good" is not quite the right word.

It's ethical, but it's usually lots of dirty code neighbouring with undefined behaviour and unportability. Do it only if you absolutely have to.

Ah, abstraction - you can't live without it and yet it is so painful to deal with sometimes :)

Anyway, ethics aside, what if the "owner" of the class decides to change the internal implementation, or simply reverses the order of the private data members?

Simple answer: No.

It is not ethical and it will turn into a maintenance nightmare at some point. The internal private members of a library can change and break your code. Developers of the library do not need to know (nor want to) that you are violating the encapsulation.

Classes usually have invariants over their methods that some times will not be documented, but accessing and changing the values from the outside can break those invariants. As an example, if you change the reserved space in a vector for a higher value, the vector will not allocate new space until it has filled the existing and that won't happen before hitting unallocated memory: your application will crash.

If the attribute is private, it is not for you to use it, only for the class itself or the the class' friends that know about the member, how to use it, how not to break it. If the programmer wanted you to change the field, it would be public.

The only "ethical" problem is what you are doing to the poor bastard who is going to have to figure out and maintain your code.

Private members are just that. He may, and most likely will, one day change that member. When that happens, you might not even notice as there most likely will still be memory there, just not the member you were expecting. Damn near any nearly impossible thing you can imagine might then start happening when your code is run. How is anybody ever going to be able to debug that?

I assume that this class is part of project you are working on.

There is one ethical problem here: If in your company you see ownership of code as sacrum. Or worst you are disallowed to modify code that is not yours. Yes You may hurt feeling of person that maintain that class. Or angry him if his salary is related to his code. so best is just to ask him for any help, and few suggestions eg. add getter function or change private to public - all based on your intuition of using that new code.

Hack that you have mention is really bed practice. If cant modify that code and maintainer dont wont to change anything. Consider using adapter design pattern.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top