Skip to content

Instantly share code, notes, and snippets.

@altamic
Last active November 8, 2023 13:14
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save altamic/d3778f906b63c6983ef074635eb36c85 to your computer and use it in GitHub Desktop.
Save altamic/d3778f906b63c6983ef074635eb36c85 to your computer and use it in GitHub Desktop.
How to access to private members and methods of a C++ class
#include <iostream>
// This is a rewrite of the technique showed here:
// http://bloglitb.blogspot.com/2010/07/access-to-private-members-thats-easy.html
// https://gist.github.com/dabrahams/1528856
// Generate a static data member of type Stub::type in which to store
// the address of a private member. It is crucial that Stub does not
// depend on the /value/ of the the stored address in any way so that
// we can access it from ordinary code without directly touching
// private data.
template <class Stub>
struct stowed
{
static typename Stub::type value;
};
template <class Stub>
typename Stub::type stowed<Stub>::value;
// Generate a static data member whose constructor initializes
// stowed<Stub>::value. This type will only be named in an explicit
// instantiation, where it is legal to pass the address of a private
// member.
template <class Stub, typename Stub::type x>
struct stow_private
{
stow_private() { stowed<Stub>::value = x; }
static stow_private instance;
};
template <class Stub, typename Stub::type x>
stow_private<Stub,x> stow_private<Stub,x>::instance;
// private instance methods
template<typename Stub>
struct result {
/* export it ... */
typedef typename Stub::type type;
static type ptr;
};
template<typename Stub>
typename result<Stub>::type result<Stub>::ptr;
template<typename Stub, typename Stub::type p>
struct stowed_method : result<Stub> {
/* fill it ... */
struct _stowed_method {
_stowed_method() { result<Stub>::ptr = p; }
};
static _stowed_method stowed_method_obj;
};
template<typename Stub, typename Stub::type p>
typename stowed_method<Stub, p>::_stowed_method stowed_method<Stub, p>::stowed_method_obj;
// Demonstration
struct A
{
A() : x("struct private instance member has been accessed") {}
private:
char const* x;
static char const* y;
void f() {
std::cout << "struct private instance method has been accessed" << std::endl;
}
static void g() {
std::cout << "struct private static method has been accessed" << std::endl;
}
};
char const* A::y = "struct private static member has been accessed"; // static member init
// A stub type for A::x. Each distinct private member you need to
// access should have its own stub. Each stub should contain a
// nested ::type that is the corresponding pointer-to-member type.
struct A_x { typedef char const*(A::*type); };
// Explicit instantiation; the only place where it is legal to pass
// the address of a private member. Generates the static ::instance
// that in turn initializes stowed<Stub>::value.
template class stow_private<A_x, &A::x>;
// This technique can also be used to access private static member variables.
struct A_y { typedef char const** type; };
template class stow_private<A_y, &A::y>;
// This technique can also be used to access private instance methods
struct Af { typedef void(A::*type)(); };
template class stowed_method<Af, &A::f>;
// and to access private static methods.
struct Ag { typedef void(*type)(); };
template class stowed_method<Ag, &A::g>;
// with a class
class B {
public:
B() { x = 42; }
private:
int x;
static int y;
void f() { printf("class private instance method: %d\n", x); }
static void g() { printf("class private static method: %d\n", 42 ); }
};
int B::y = 42; // initialize static member
struct B_x { typedef int (B::*type); };
template class stow_private<B_x, &B::x>;
struct B_y { typedef const int *type; };
template class stow_private<B_y, &B::y>;
struct Bf { typedef void(B::*type)(); };
template class stowed_method<Bf, &B::f>;
struct Bg { typedef void(*type)(); };
template class stowed_method<Bg, &B::g>;
int main()
{
A a;
// Use the stowed private member pointer
std::cout << a.*stowed<A_x>::value << std::endl;
// Use the stowed private static member pointer
std::cout << *stowed<A_y>::value << std::endl;
// Use the stowed private method member pointer
(a.*result<Af>::ptr)();
// Use the stowed private static method member pointer
(*result<Ag>::ptr)();
B b = B();
// Use the stowed private member pointer
printf("class private instance member: %d\n", b.*stowed<B_x>::value);
// Use the stowed private static member pointer
printf("class private static member: %d\n", *stowed<B_y>::value);
// Use the stowed private method member pointer
(b.*result<Bf>::ptr)();
// Use the stowed private static method member pointer
(*result<Bg>::ptr)();
};
/*
$ clang++ private_access.cpp -o private_access
$ ./private_access
struct private instance member has been accessed
struct private static member has been accessed
struct private instance method has been accessed
struct private static method has been accessed
class private instance member: 42
class private static member: 42
class private instance method: 42
class private static method: 42
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment