In the following code, which I found here:
http://bloglitb.blogspot.com/2010/07/access-to-private-members-thats-easy.html
it appears to step right across C++'s private access specifier. It allows me to call private functions and read/write private data members.
Searching SO found this related issue which was a confirmed GCC compiler bug
c++ template seems to break access specifiers
So naturally I tried using that guy's test code. What was interesting is that my gcc 4.5 compiler indeed has that bug ( it accepts the code and prints the private info ) despite it being reported in gcc 4.3 and me using 4.5.
Anyway, I then went to the Comeau online compiler, which some of the responses to the thread said they tried. I confirmed Comeau does not accept the code from that question, but it does accept my code below.
So ultimately my question is, have I stumbled across a bug in GCC and Comeau's C++ compiler ? Does this compile with VC++ ? If it's not a bug, can someone explain how it works ? I get that it's able to declare a static member function pointer and point it to the private section, but how is it accomplishing this ?
Misc notes: Yes, I know that actually doing this is Very Very Bad. This will also work if you declare a member data ptr and allow you to read/write to private data. Some of the weird comments were from me trying to label it for understanding. I did not conjure up this code and I take no credit for it. I just found it on google. I may not have enough reputation points to reply to comments but I will read everything you say. Thanks for taking a look.
#include <iostream>
using namespace std;
//--------------------------------------------
//
template<typename Tag>
struct result
{
/* export it ... */
typedef typename Tag::type type;
static type ptr;
};
// allocate space for the static member
template<typename Tag>
typename result<Tag>::type result<Tag>::ptr;
//--------------------------------------------
template<typename Tag, typename Tag::type p>
struct rob : result<Tag>
{
/* fill it ... */
struct filler
{
filler() { result<Tag>::ptr = p; }
};
static filler filler_obj;
};
// allocate space for the static member
template<typename Tag, typename Tag::type p>
typename rob<Tag, p>::filler rob<Tag, p>::filler_obj;
//--------------------------------------------
struct A
{
private:
void f()
{
cout << "hey, don't touch me I'm private!" << endl;
}
};
struct Af
{
typedef void(A::*type)();
};
template class rob<Af, &A::f>;
int main()
{
A a;
(a.*result<Af>::ptr)();
}
~> ./a.out hey, don't touch me I'm private!
~> g++ --version g++ (SUSE Linux) 4.5.0 20100604 [gcc-4_5-branch revision 160292] Copyright (C) 2010 Free Software Foundation, Inc.
As a Loki Astari said, public and private are just semantics for the compiler so it can give you warnings that you're not using your code the way you intended.
I don't play with method pointers much (if at all), so I haven't the patience to figure this out fully. But it's no different to doing a mixture of the following. That is to say, using pointer logic to point at whatever bit of memory you want and casting functions and methods and misusing them.
#include <iostream>
using namespace std;
struct A
{
public:
void g()
{
cout << "value of i is " << this->i << endl;
}
void setJ(int newJ) {
j = newJ;
}
int i;
private:
int j;
};
int main() {
A a;
a.i = 5;
a.setJ(10);
// accessing private field j
cout << "value of j is " << *((&a.i)+1) << endl;
// creating a pointer to method g
void(A::*method)() = &A::g;
// changing it to be a function pointer
void(*function)(A*) = (void(*)(A*)) method;
// using function pointer to call A::g
function(&a);
return 0;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With