views:

5155

answers:

13

Disclaimer

Yes, I am fully aware that what I am asking about is totally stupid and that anyone who would wish to try such a thing in production code should be fired and/or shot. I'm mainly looking to see if can be done.

Now that that's out of the way, is there any way to access private class members in C++ from outside the class? For example, is there any way to do this with pointer offsets?

(Naive and otherwise non-production-ready techniques welcome)

Update

As noted in the comments, I asked this question because I wanted to write a blog post on over-encapsulation (and how it affects TDD). I wanted to see if there was a way to say "using private variables isn't a 100% reliable way to enforce encapsulation, even in C++." At the end, I decided to focus more on how to solve the problem rather than why it's a problem, so I didn't feature some of the stuff brought up here as prominently as I had planned, but I still left a link.

At any rate, if anyone's interested in how it came out, here it is: Enemies of Test Driven Development part I: encapsulation (I suggest reading it before you decide that I'm crazy).

+2  A: 

If you know how your C++ compiler mangles names, yes.

Unless, I suppose, it's a virtual function. But then, if you know how your C++ compiler builds the VTABLE ...

Edit: looking at the other responses, I realize that I misread the question and thought it was about member functions, not member data. However, the point still stands: if you know how your compiler lays out data, then you can access that data.

kdgregory
I find this answer interesting because the biggest argument against using Python's private members is that it's really just name mangling (albeit a more standardized name mangling). It's interesting to know that things are about the same in C++.
Jason Baker
Jason - the difference is, in Python, you may get your wrist slapped for accessing privates. In C++, your fellow developers will shoot you for going to these lengths to subvert encapsulation.
Tom
+5  A: 

The following is sneaky, illegal, compiler-dependent, and may not work depending on various implementation details.

#define private public
#define class struct

But it is an answer to your OP, in which you explicitly invite a technique which, and I quote, is "totally stupid and that anyone who would wish to try such a thing in production code should be fired and/or shot".


Anothr technique is to access private member data, by contructing pointers using hard-coded/hand-coded offsets from the begining of the object.

ChrisW
You also need #define class struct, otherwise the private-by-default may thwart you.
Tom
Preprocessor hacks are no more access to private members than pointer dereferencing is.
cletus
rq is wrong on the mechanism (relaxing access checks never invalidate a valid program, due to the moment when they happen). The hack violates the ODR and might break the program due to name mangling.
MSalters
Sorry does not work on all compilers.
Martin York
Edited the post, to reference the "disclaimer" in the OP.
ChrisW
+1 Tom. (padding to get past 10 character limit...)
j_random_hacker
@MSalters it will break (on vc2005) when attempting to link a (now) public constructor to a private constructor in the .lib file.
Aaron
I've tried this trick in order to add unit tests to some legacy code with mixed results. It seemed to work for private data but not private methods. Apparently the compiler I was using (VC++ 9.0) included a method's visibility as part of its name mangling scheme.
Ferruccio
A: 

Beside #define private public you can also #define private protected and then define some foo class as descendant of wanted class to have access to it's (now protected) methods via type casting.

dmajkic
+8  A: 

Hmmm, don't know if this would work, but might be worth a try. Create another class with the same layout as the object with private members but with private changed to public. Create a variable of pointer to this class. Use a simple cast to point this to your object with private members and try calling a private function.

Expect sparks and maybe a crash ;)

Shane MacLaughlin
i like it, in theory should work.
Evan Teran
"with the same layout". This is the hard part. The compiler has a good bit of freedom on how it lays out members in a non-POD. In practice though, it will probably work.
Richard Corden
@Richard Corden - That would be my feeling as well. Illustrating once againa that 'Would probably work' and 'should be done in a piece of release' are worlds apart.
Shane MacLaughlin
+1 to Richard Corden
Marcin
Thats an interesting one..I expected most to give the answer involving pointer offsets. I want to try out this one.
Naveen
Bear in mind that the compiler is perfectly free to reorder members based on access control (actually, it's perfectly free to reorder if there is any access control). I don't know how many actually do this....
David Thornley
Most compilers will not reorder members - they're not permitted to do so for POD structures, or else they would break compatibility with C structures (struct sockaddr, for one). Really, there's very little incentive to provide automatic member reordering.
Tom
A: 

just create your own access member function to extend the class.

Richard Riley
+3  A: 

It's definately possible to access private members with a pointer offset in C++. Lets assume i had the following type definition that I wanted access to.

class Bar {
  SomeOtherType _m1;
  int _m2;
};

Assuming there are no virtual methods in Bar, The easy case is _m1. Members in C++ are stored as offsets of the memory location of the object. The first object is at offset 0, the second object at offset of sizeof(first member), etc ...

So here is a way to access _m1.

SomeOtherType& GetM1(Bar* pBar) {
  return*(reinterpret_cast<SomeOtherType*>(pBar)); 
}

Now _m2 is a bit more difficult. We need to move the original pointer sizeof(SomeOtherType) bytes from the original. The cast to char is to ensure that I am incrementing in a byte offset

int& GetM2(Bar* pBar) {
  char* p = reinterpret_cast<char*>(pBar);
  p += sizeof(SomeOtherType);
  return *(reinterpret_cast<int*>(p));
}
JaredPar
Watch out for memory padding and alignment issues. But +1 certainly doable!
Mr.Ree
A: 

To all the people suggesting "#define private public":

This kind of thing is illegal. The standard forbids defining/undef-ing macros that are lexically equivalent to reserved language keywords. While your compiler probably won't complain (I've yet to see a compiler that does), it isn't something that's a "Good Thing" to do.

Tritium
But you'll note that the question doesn't require that this be a "good thing" to do. In fact, a good way to do this may not exist.
Jason Baker
Well, the question *does* require that the method work, right? Since the standard forbids this sort of thing the method outlined by other is simply broken by definition. It works because most compilers don't enforce this **rule**.
Tritium
Jason, the question requires that this can be done. at least when you include a standard header, then you run into undefined behavior, and that can't be an answer to this question. turning stuff into undefined behavior allows the compiler to do just about anything it wants. (formatting your HD)
Johannes Schaub - litb
(and including forbidding you to access the privates - which ironically is just what the questioner does *not* want). It's as far as i know allowed to #define keywords when there is no standard header included into the same translation unit though. but as i said, that can't be the solution!
Johannes Schaub - litb
litb, your logic isn't quite right. It's is explicitly FORBIDDEN to define a macro name that is lexically identical to ANY reserved keyword, regardless of what you include in a translation unit. It's as simple as: "don't do it, it's illegal".
Tritium
Tritium - In the context of this question, the standard doesn't matter. Anyone subverting the language's built-in access control mechanisms only cares if it works or not in their given environment. Anyone who -ansi-pedantic-ally adheres about the standard wouldn't be doing this in the first place.
Tom
1. Given the fact that people actually responded with this suggestion in the first place says that they didn't know that this was illegal.2. By your logic, people will also be dereferencing null pointers, writing past array bounds, etc. because it happens to "work" on their machine.
Tritium
A: 

It's actually quite easy:

class jail {
    int inmate;
public:
    int& escape() { return inmate; }
};
MSalters
I assume that the OP wants access **without modifying the class definition itself**.
j_random_hacker
For Test-Driven Development, such backdoors could make sense. They're easy to remove with a #define. #define's that mess with public/private can affect program semantics, e.g. POD-ness.
MSalters
+14  A: 

If the class contains any template member functions you can specialize that member function to suit your needs. Even if the original developer didn't think of it.

safe.h

class safe
{
    int money;

public:
    safe()
     : money(1000000)
    {
    }

    template <typename T>
    void backdoor()
    {
        // Do some stuff.
    }
};

main.cpp:

#include <safe.h>
#include <iostream>

class key;

template <>
void safe::backdoor<key>()
{
    // My specialization.
    money -= 100000;
    std::cout << money << "\n";
}

int main()
{
    safe s;
    s.backdoor<key>();
    s.backdoor<key>();
}

Output:

900000
800000
dalle
There is a potential that key will clash. Put it in an anonymous namespace.
Martin York
+3  A: 

If you can get a pointer to a member of a class you can use the pointer no matter what the access specifiers are (even methods).

class X;
typedef void (X::*METHOD)(int);

class X
{
    private:
       void test(int) {}
    public:
       METHOD getMethod() { return &X::test;}
};

int main()
{
     X      x;
     METHOD m = x.getMethod();

     X     y;
     (y.*m)(5);
}

Of course my favorite little hack is the friend template back door.

class Z
{
    public:
        template<typename X>
        void backDoor(X const& p);
    private:
        int x;
        int y;
};

Assuming the creator of the above has defined backDoor for his normal uses. But you want to access the object and look at the private member variables. Even if the above class has been compiled into a static library you can add your own template specialization for backDoor and thus access the members.

namespace
{
    // Make this inside an anonymous namespace so
    // that it does not clash with any real types.
    class Y{};
}
// Now do a template specialization for the method.
template<>
void Z::backDoor<Y>(Y const& p)
{
     // I now have access to the private members of Z
}

int main()
{
    Z  z;   // Your object Z

    // Use the Y object to carry the payload into the method.
    z.backDoor(Y());
}
Martin York
+4  A: 
class A 
{ 
   int a; 
}
class B
{
   public: 
   int b;
}

union 
{ 
    A a; 
    B b; 
};

That should do it.

ETA: It will work for this sort of trivial class, but as a general thing it won't. TC++PL Section C.8.3 says "A class with a constructor, destructor, or copy operation cannot be the type of a union member ... because the compiler would not know which member to destroy."

So we're left with the best bet being to declare class B to match A's layout, then using B * b = reinterpret_cast<B*>(&a); as the "best" "peeping tom" hack to look at a class's privates.

Rob K
sounds like a good idea ..
hasen j
No, no, no, not at all a good idea. Just because you can do it, doesn't mean you should.
Rob K
A: 

since you have an object of required class I am guessing that you have declaration of class. Now what you can do is declare another class with same members but keep all of there access specifiers as public. For example previous class is: class Iamcompprivate {

private:

Type1 privateelement1;
Typ2 privateelement2;

...........

public:

somefunctions

}

you can declare a class as class NowIampublic {

public:

Type1 privateelement1;
Type2 privateelement2;

. .

somefunctions

}

Now all you need to do is cast pointer of class Iamcompprivate into an pointer of class NowIampublic and use them as U wish. Example:

NowIampublic * changetopublic(Iamcompprivate *A) {

NowIampublic * B=(NowIampublic *)A;

return B;

}

Alok
+2  A: 

I've just added an entry to my blog that shows how it can be done. 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.

Johannes Schaub - litb