Can I access private members from outside the class without using friends?


Question

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).

1
62
1/8/2009 4:36:18 PM

Accepted Answer

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
67
1/8/2009 4:43:42 PM

I've added an entry to my blog (see below) 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 struct for it where you describe it and instantiate the implementation class used for robbery

// tag used to access A::member
struct A_member { 
  typedef int A::*type;
  friend type get(A_member);
};

template struct Rob<A_member, &A::member>;

int main() {
  A a;
  a.*get(A_member()) = 42; // write 42 to it
  std::cout << "proof: " << a.*get(A_member()) << std::endl;
}

The Rob class template is defined like this, and needs only be defined once, regardless how many private members you plan to access

template<typename Tag, typename Tag::type M>
struct Rob { 
  friend typename Tag::type get(Tag) {
    return M;
  }
};

However, 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.


Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon