Last active
February 27, 2025 22:34
-
-
Save altamic/d3778f906b63c6983ef074635eb36c85 to your computer and use it in GitHub Desktop.
How to access to private members and methods of a C++ class
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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