C++ 我可以在不使用好友的情况下从课外访问私人成员吗? 免责声明

C++ 我可以在不使用好友的情况下从课外访问私人成员吗? 免责声明,c++,encapsulation,private-members,C++,Encapsulation,Private Members,是的,我完全知道我所问的完全是愚蠢的,任何想在生产代码中尝试这种事情的人都应该被解雇和/或枪毙。我主要是想看看能不能做到 现在,这是不是可以,有没有办法从C++外部访问C++中的私有类成员?例如,有没有任何方法可以通过指针偏移来实现这一点 欢迎使用幼稚或其他不适合生产的技术 使现代化 正如评论中提到的,我问这个问题是因为我想写一篇关于过度封装及其如何影响TDD的博客文章。我想看看是否有办法说使用私有变量不是强制封装的100%种可靠方法,即使是在C++中。最后,我决定更多地关注如何解决问题,而不是

是的,我完全知道我所问的完全是愚蠢的,任何想在生产代码中尝试这种事情的人都应该被解雇和/或枪毙。我主要是想看看能不能做到

<>现在,这是不是可以,有没有办法从C++外部访问C++中的私有类成员?例如,有没有任何方法可以通过指针偏移来实现这一点

欢迎使用幼稚或其他不适合生产的技术

使现代化 正如评论中提到的,我问这个问题是因为我想写一篇关于过度封装及其如何影响TDD的博客文章。我想看看是否有办法说使用私有变量不是强制封装的100%种可靠方法,即使是在C++中。最后,我决定更多地关注如何解决问题,而不是为什么它是一个问题,因此我没有像我计划的那样突出地介绍这里提到的一些内容,但我仍然留下了一个链接


不管怎样,如果有人对它的出现感兴趣,这里是:我建议在你决定我疯了之前先阅读它。

< P>如果你知道C++编译器如何修改名字,是的。 除非,我想,这是一个虚拟函数。但是,如果你知道C++编译器是如何构建VTABLE……/P>
编辑:看看其他的回答,我意识到我误读了这个问题,认为是关于成员函数,而不是成员数据。但是,问题仍然存在:如果您知道编译器如何布局数据,那么您可以访问该数据。

以下内容是秘密的、非法的、依赖于编译器的,并且可能无法根据各种实现细节工作

#define private public
#define class struct
但这是对你的OP的一个回答,在你的OP中,你明确地邀请了一种技术,我引用它,这是完全愚蠢的,任何想在生产代码中尝试这种东西的人都应该被解雇和/或枪毙


另一种技术是访问私有成员数据,方法是使用从对象开始的硬编码/手工编码偏移量构造指针。

除了定义private-public,您还可以定义private-protected,然后将某个foo类定义为所需类的后代,以便通过类型转换访问其现在受保护的方法

嗯,我不知道这是否有效,但可能值得一试。创建另一个类,该类的布局与具有私有成员但将私有更改为公共的对象相同。创建指向此类的指针变量。使用简单的强制转换将其指向具有私有成员的对象,并尝试调用私有函数


期待着火花,也许是碰撞

> P>只需创建自己的Access成员函数来扩展类。

< P>可以用C++中的指针偏移来访问私有成员。让我们假设我有以下我想要访问的类型定义

class Bar {
  SomeOtherType _m1;
  int _m2;
};
假设Bar中没有虚方法,那么简单的情况是_m1。C++中的成员作为对象内存位置的偏移量存储。第一个对象的偏移量为0,第二个对象的偏移量为sizeoffirst成员,等等

所以这里有一种访问_m1的方法

SomeOtherType& GetM1(Bar* pBar) {
  return*(reinterpret_cast<SomeOtherType*>(pBar)); 
}
现在,m2有点困难。我们需要将原始指针sizeofSomeOtherType字节从原始指针移动。转换为char是为了确保我在字节偏移量中递增

int& GetM2(Bar* pBar) {
  char* p = reinterpret_cast<char*>(pBar);
  p += sizeof(SomeOtherType);
  return *(reinterpret_cast<int*>(p));
}

对于所有建议定义私人和公共的人:


这种事是违法的。该标准禁止定义/取消定义在词汇上等同于保留语言关键字的宏。虽然您的编译器可能不会抱怨,但我还没有看到这样的编译器,这并不是一件好事。

实际上很简单:

class jail {
    int inmate;
public:
    int& escape() { return inmate; }
};

如果类包含任何模板成员函数,则可以专门化该成员函数以满足您的需要。即使最初的开发者没有想到它

安全

class safe
{
    int money;

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

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

如果您可以获得指向类成员的指针,那么无论访问说明符是什么,您都可以使用该指针

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);
}
当然,我最喜欢的小黑客是朋友模板后门

class Z
{
    public:
        template<typename X>
        void backDoor(X const& p);
    private:
        int x;
        int y;
};
假设上述内容的创建者已经为其正常使用定义了后门。但是您希望访问对象并查看私有成员变量。即使上面的类已编译成静态库,您也可以为后门添加自己的模板专门化,从而访问成员

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());
}
应该这样做

ETA:它适用于这种琐碎的类,但一般来说不会

TC++PL第C.8.3节:具有构造函数、析构函数或复制操作的类不能是联合成员的类型。。。因为编译器不知道要销毁哪个成员


因此,我们剩下的最佳选择是声明类B以匹配A的布局,并破解以查看类的私密性。

既然您有一个必需类的对象,我猜您已经声明了类。 现在你能做的就是 是另一个具有相同成员但将所有访问说明符保持为公共的类

例如,前面的类是:

class Iamcompprivate
{
private:
    Type1 privateelement1;
    Typ2 privateelement2;
    ...

public:
    somefunctions
}
可以将类声明为

class NowIampublic
{
**public:**
    Type1 privateelement1;
    Type2 privateelement2;
    ...

    somefunctions
};
现在,您需要做的就是将类Iamcompprivate的指针强制转换为类NowIampublic的指针,并按照您的意愿使用它们

例如:

NowIampublic * changetopublic(Iamcompprivate *A)
{
    NowIampublic * B = (NowIampublic *)A;
    return B;
}
我在下面添加了一个see,它显示了如何实现这一点。下面是一个关于如何在下面的类中使用它的示例

struct A {
private:
  int member;
};
只需在描述它的地方为它声明一个结构,并实例化用于实现的实现类

// 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;
}
然而,这并不表明c++的访问规则是不可靠的。语言规则是为了防止意外错误而设计的——如果您试图盗取某个对象的数据,设计语言不会花很长时间来阻止您

使用私有变量不是强制封装的100%种可靠方法,即使在C++中也是如此。 真正地您可以分解所需的库,找到所需的所有偏移量并使用它们。 这将使你有能力改变你喜欢的任何私人成员。。。但是 如果没有恶意的黑客攻击,你无法访问私人成员。 让我们说,写常量不会使你的常量成为真正的常量,因为你可以 丢弃常量,或者使用它的地址使其无效。如果您使用的是MSVC++并且指定了-merge:.rdata=.data到链接器,那么该技巧将在没有任何内存访问错误的情况下工作。 我们甚至可以说,用C++编写应用程序并不是编写程序的可靠方法,因为当应用程序运行时,可能会从外部某个地方修补低级代码。 那么什么是可靠的文档化方法来强制封装呢?我们可以将数据隐藏在RAM中的某个地方,并阻止除代码之外的任何东西访问它们吗?我唯一的想法就是加密私人成员并对其进行备份,因为有些东西可能会损坏这些成员。
对不起,如果我的回答太粗鲁,我不是有意冒犯任何人,但我真的认为这种说法不明智。

很酷的问题顺便说一句。。。这是我的作品:

using namespace std;

class Test
{

private:

  int accessInt;
  string accessString;

public:

  Test(int accessInt,string accessString)
  {
    Test::accessInt=accessInt;
    Test::accessString=accessString;
  }
};

int main(int argnum,char **args)
{
  int x;
  string xyz;
  Test obj(1,"Shit... This works!");

  x=((int *)(&obj))[0];
  xyz=((string *)(&obj))[1];

  cout<<x<<endl<<xyz<<endl;
  return 0;
}
希望这有帮助。

通过引用*这一点,您可以为对象中的所有私有数据启用后门

class DumbClass
{
private:
    int my_private_int;
public:
    DumbClass& backdoor()
    {
        return *this;
    }
}

作为模板后门方法的替代方法,您可以使用模板后门类。不同之处在于,您不需要将这个后门类放到您要测试的类的公共区域。我使用的事实是,许多编译器允许嵌套类访问封闭类的私有区域,这并不完全是1998年的标准,但被认为是正确的行为。当然,在C++11中,这成为了法律行为

请参见此示例:

#include <vector>
#include <cassert>
#include <iostream>
using std::cout;
using std::endl;


///////// SystemUnderTest.hpp
class SystemUnderTest
{
   //...put this 'Tested' declaration into private area of a class that you are going to test
   template<typename T> class Tested;
public:
   SystemUnderTest(int a): a_(a) {}
private:
   friend std::ostream& operator<<(std::ostream& os, const SystemUnderTest& sut)
   {
      return os << sut.a_;
   }
   int a_;
};

/////////TestFramework.hpp
class BaseTest
{
public:
   virtual void run() = 0;
   const char* name() const { return name_; }
protected:
   BaseTest(const char* name): name_(name) {}
   virtual ~BaseTest() {}
private:
   BaseTest(const BaseTest&);
   BaseTest& operator=(const BaseTest&);
   const char* name_;
};

class TestSuite
{
   typedef std::vector<BaseTest*> Tests;
   typedef Tests::iterator TIter;
public:
   static TestSuite& instance()
   {
      static TestSuite TestSuite;
      return TestSuite;
   }
   void run()
   {
      for(TIter iter = tests_.begin(); tests_.end() != iter; ++iter)
      {
         BaseTest* test = *iter;
         cout << "Run test: " << test->name() << endl;
         test->run();
      }
   }
   void addTest(BaseTest* test)
   {
      assert(test);
      cout << "Add test: " << test->name() << endl;
      tests_.push_back(test);
   }
private:
   std::vector<BaseTest*> tests_;
};

#define TEST_CASE(SYSTEM_UNDER_TEST, TEST_NAME) \
class TEST_NAME {}; \
template<> \
class SYSTEM_UNDER_TEST::Tested<TEST_NAME>: public BaseTest \
{ \
   Tested(): BaseTest(#SYSTEM_UNDER_TEST "::" #TEST_NAME) \
   { \
      TestSuite::instance().addTest(this); \
   } \
   void run(); \
   static Tested instance_; \
}; \
SYSTEM_UNDER_TEST::Tested<TEST_NAME> SYSTEM_UNDER_TEST::Tested<TEST_NAME>::instance_; \
void SYSTEM_UNDER_TEST::Tested<TEST_NAME>::run()


//...TestSuiteForSystemUnderTest.hpp
TEST_CASE(SystemUnderTest, AccessPrivateValueTest)
{
   SystemUnderTest sut(23);
   cout << "Changed private data member from " << sut << " to ";
   sut.a_ = 12;
   cout << sut << endl;
}

//...TestRunner.cpp
int main()
{
   TestSuite::instance().run();
}

类通常为私有数据获取者和设置者提供mutator方法

如果一个类确实提供了一个返回常量引用但没有setter的getter,那么您可以对getter的返回值进行const_强制转换,并将其用作l值:

class A {
  private:
    double _money;
  public:
    A(money) :
      _money(money)
    {}

    const double &getMoney() const
    {
      return _money;
    }
};

A a(1000.0);
const_cast<double &>(a.getMoney()) = 2000.0;

我使用了另一种有用的方法和解决方案来访问C++私有/受保护成员。 唯一的条件是您能够从要访问的类继承。 然后,所有的功劳都归于重新解释

一个可能的问题是,如果插入一个虚拟函数,它将无法工作,这将修改虚拟表以及对象大小/对齐方式

然后您只需要按如下方式使用该类:

QObject* origin;
QObjectWrapper * testAccesor = reinterpret_cast<QObjectWrapper *>(origin);
testAccesor->dumpObjectInfo2();
testAccesor->dumpObjectTree2();
我最初的问题如下:我需要一个不需要重新编译QT库的解决方案。 QObject中有两个方法,dumpObjectInfo和dumpObjectTree 如果qtlib是在调试模式下编译的,那么它就可以工作,当然它们需要访问d_ptr protected member和其他内部结构。
我所做的是使用建议的解决方案在我自己的类QObjectWrapper中复制并粘贴DumpObjectInfo 2和dumpObjectTree2中的这些方法来重新实现,删除那些调试前处理器保护。

以下代码使用指向该类的指针访问和修改该类的私有成员

#include <iostream>
using namespace std;
class A
{
    int private_var;
    public:
    A(){private_var = 0;}//initialized to zero.
    void print(){cout<<private_var<<endl;}
};

int main()
{
    A ob;
    int *ptr = (int*)&ob; // the pointer to the class is typecast to a integer pointer.  
    (*ptr)++; //private variable now changed to 1.
    ob.print();
    return 0;
}
/*prints 1. subsequent members can also be accessed by incrementing the pointer (and
  type casting if necessary).*/
方法一:侵入性语气。 因为我们可以访问源代码并重新编译它,所以我们可以使用 还有很多其他的方式,比如朋友类访问私有成员,它们都是合法的后门

方法二:野蛮的情绪

我们也无法从类测试中获取成员指针。 前

@Johannes Schaub-litb有一个博客,他找到了一种抢劫私人会员的方法。 但我认为这应该是编译器的bug或语言陷阱。 我可以在gcc4.8上编译,但不能在vc8编译器上编译

因此,结论可能是: 房东建造了所有的后门。 小偷总是有凶残的破门而入的手段。 黑客有一种优雅的、自动的方式来入侵

仅用于学习目的。。。。 试试这个……我想可能会有帮助。。。。。 这个程序只需知道值就可以访问私有数据

//GEEK MODE....;)
#include<iostream.h>
#include<conio.h>

    class A
    {
    private :int iData,x;
    public: void get()             //enter the values
        {cout<<"Enter iData : ";
            cin>>iData;cout<<"Enter x : ";cin>>x;}

        void put()                               //displaying values
    {cout<<endl<<"sum = "<<iData+x;}
};

void hack();        //hacking function

void main()
{A obj;clrscr();
obj.get();obj.put();hack();obj.put();getch();
}

void hack()         //hack begins
{int hck,*ptr=&hck;
cout<<endl<<"Enter value of private data (iData or x) : ";
cin>>hck;     //enter the value assigned for iData or x
for(int i=0;i<5;i++)
{ptr++;
if(*ptr==hck)
{cout<<"Private data hacked...!!!\nChange the value : ";
cin>>*ptr;cout<<hck<<" Is chaged to : "<<*ptr;
return;}
}cout<<"Sorry value not found.....";
}

这个答案是基于所证明的确切概念,因为这似乎是唯一合法的方式。我已将该示例代码转换为一个方便的实用程序。通过实现std::remove_引用并替换nullptr,它很容易与C++03兼容

图书馆 美国石油学会 用法 我 由@johannesschaub-litb编写,下面的代码可能更容易理解

    struct A {
    A(): member(10){}
    private:
    int get_member() { return member;}
    int member;
   };

   typedef int (A::*A_fm_ptr)();
   A_fm_ptr  get_fm();

  template<   A_fm_ptr p> 
  struct Rob{ 
     friend A_fm_ptr  get_fm() {
   return p;
  }
};

 template struct Rob<  &A::get_member>;

 int main() {
   A a;
  A_fm_ptr p = get_fm();

    std::cout << (a.*p)() << std::endl;

  }

有了指针偏移,这很容易。困难的部分是找到偏移:

其他.水电站 main.cpp 输出:

私人: 您还可以使用reinterpret_cast。

我做了更通用的解释。您可以在此处获取来源: 您只需要知道类和成员的名称

你可以用like

#include <iostream>

#include "access/access.hpp"

struct foo {
 private:
  std::string name = "hello";
  int age = 27;
  void print() {}
};

using tag_foo_name = access::Tag<class foo_name>;
template struct access::Accessor<tag_foo_name, foo, decltype(&foo::name), &foo::name>;

int main() {
  foo f;
  
  // peek hidden data
  std::cout << access::get<tag_foo_name>(f) << '\n'; // "hello"
  
  // steal hidden data
  access::get<tag_foo_name>(f) = "lupin";
  std::cout << access::get<tag_foo_name>(f) << '\n'; // "lupin"
}


调用私有函数,也可以仅使用标签获取私有成员的类型。

使用相同的布局。这是最难的部分。编译器在如何在非POD中布局成员方面有很大的自由度。但在实践中,它可能会起作用。@Richard Corden-这也是我的感觉。再次说明“可能会工作”和“应该在一个版本中完成”是两码事。请记住,编译器完全可以根据访问控制对成员进行重新排序。实际上,如果有任何访问控制,则完全可以重新排序。我不知道有多少编译器会这样做……大多数编译器不会对成员进行重新排序——例如,POD结构不允许他们这样做,否则他们会破坏与C结构struct sockaddr的兼容性。实际上,提供自动成员重新排序的动机很小。您还需要定义类结构,否则默认情况下私有成员可能会阻止您。预处理器黑客对私有成员的访问与指针取消引用的访问不同。rq在机制上是错误的放松访问检查不会使有效程序无效,因为它们发生的那一刻。该黑客违反了ODR,可能会因为名称混乱而破坏程序。对于使用Xcode 6 LLVM的TDD也很有效,这个答案是解决我的问题的最佳解决方案,根本不需要修改原始代码。在某些情况下,这不起作用,因为类可以在模板参数中使用,与typename相同,但是struct不能。出于兴趣,为什么要问这个问题。我所能想到的唯一用途就是侵入别人的API来制造混乱。我正在写一篇关于过度封装的博客文章。我只是想看看是否有可能说,保护方法是不完美的,即使在C++中。一旦我把链接写好了,我会发布它。但是你会注意到,这个问题并不要求这是一件好事。事实上,这样做的好方法可能不存在。好吧,问题确实要求这种方法有效,对吗?由于标准禁止这种事情,其他人概述的方法被定义破坏了。它之所以有效,是因为大多数编译器都不执行这一规则。Jason,问题是,这是可以做到的。至少当您包含一个标准标题时,您会遇到未定义的行为,而这并不是这个问题的答案。将内容转换为未定义的行为允许编译器做任何它想做的事情。格式化你的HDL,包括禁止你进入私人空间——讽刺的是,这正是提问者不想要的。据我所知,在同一翻译单元中没有包含标准标题的情况下,可以定义关键字。但正如我所说,这不是解决办法!利特,你的逻辑不太正确。明确禁止定义与任何保留关键字在词汇上相同的宏名称,无论翻译单元中包含什么。这很简单:不要这样做,这是非法的。我觉得这个答案很有趣,因为反对使用Python的私有成员的最大理由是,它实际上只是名称篡改,尽管是更标准化的名称篡改。有趣的是,在C++中,事情是一样的。杰森的不同之处在于,在Python中,你可能会因为访问私有程序而被拍打手腕。在C++中,你的开发人员会向你开枪,用这些长度来破坏封装。注意内存填充和对齐问题。但是+1肯定是可行的!我假设OP希望在不修改类定义本身的情况下进行访问。对于测试驱动的开发,这样的后门是有意义的。它们很容易通过定义删除。定义公共/私有的混乱会影响程序语义,例如POD-ness。存在密钥冲突的可能性。把它放在一个匿名名称空间中。语言规则不是吗?这似乎不起作用。它适用于您博客上的私有函数示例,但对于int I get:error:int A::*“类型的非类型模板参数必须具有模板类rob的整数或枚举类型;如果答案看起来很棘手,请注意两个要点:1模板结构Rob:显式实例化定义忽略成员访问说明符:参数类型和返回类型可能是私有的2 a.*getA_成员调用非成员友元函数getA_成员,该函数返回&a::member。这之所以有效是因为。尝试删除get函数的无用参数,您应该知道get未在此范围内声明,我将
我很想看到有关此行为的简明解释。如果::member不是int,而是枚举Foo,其中名称Foo在中是私有的,那么是否有可能对这种情况进行修改?这是一种理想的情况,您知道类实例变量布局。但是,如果类具有具有IVAR的祖先或具有虚拟成员,则这种情况是不正确的。尽管如此,您仍然需要基于特定实现的知识来制定解决方案。所以,基本上,你没有回答最初的问题,我可以不使用friends从类外访问私有成员吗?你展示了如何在特定的实现中访问类私有成员的内存。这听起来像是对其他答案的咆哮,而不是答案。你有足够的声誉在其他答案上留下清晰的评论。对不起,我没有学会正确的讨论规则。但结论是真实的,这是我思考的结果。问题是关于语言本身,而不是关于你能做或不能做的平台细节。我不能对enum Foo类型的私有成员使用这一点,其中Foo也在私有部分,因为Class::Foo由于是私有的,不能在ALLOW\u ACCESS宏中使用!有什么建议吗?@M.M不知道该怎么做。他几乎没有尝试其他办法,但毫无结果。如果找到解决方案,将更新。未定义的行为是undefined@formerlyknownas_463035818仅来自具有访问权限的方法。如果一个方法有权访问一个方法,它可以获取一个指向函数的指针并返回它。一旦你有了指针,它就可以被传递和使用,因为对该指针没有权限。@formerlyknownas_463035818 1:test是私有的,getMethod返回的值是公有的,可以是任何值。2:不,您无法从外部获取指针。谢谢您的评论。我花了一段时间才意识到,我每天使用的几乎所有课程都有后门。我以前知道最好不要开门,现在我也知道在哪里可以找到它。如果你不介意,我会删除我的评论,我想你也会删除你的评论
QObject* origin;
QObjectWrapper * testAccesor = reinterpret_cast<QObjectWrapper *>(origin);
testAccesor->dumpObjectInfo2();
testAccesor->dumpObjectTree2();
#include <iostream>
using namespace std;
class A
{
    int private_var;
    public:
    A(){private_var = 0;}//initialized to zero.
    void print(){cout<<private_var<<endl;}
};

int main()
{
    A ob;
    int *ptr = (int*)&ob; // the pointer to the class is typecast to a integer pointer.  
    (*ptr)++; //private variable now changed to 1.
    ob.print();
    return 0;
}
/*prints 1. subsequent members can also be accessed by incrementing the pointer (and
  type casting if necessary).*/
class Test{
    int a;
    alignas(16) int b;
    int c;
};

Test t;
int* ptr_of_member_c = reinterpret_cast<int*>(reinterpret_cast<char*>(&t) + 20);
offsetof(Test,c); //complie error. they said can not access private member.
&Test::c ;  //complie error. they said can not access private member.
//GEEK MODE....;)
#include<iostream.h>
#include<conio.h>

    class A
    {
    private :int iData,x;
    public: void get()             //enter the values
        {cout<<"Enter iData : ";
            cin>>iData;cout<<"Enter x : ";cin>>x;}

        void put()                               //displaying values
    {cout<<endl<<"sum = "<<iData+x;}
};

void hack();        //hacking function

void main()
{A obj;clrscr();
obj.get();obj.put();hack();obj.put();getch();
}

void hack()         //hack begins
{int hck,*ptr=&hck;
cout<<endl<<"Enter value of private data (iData or x) : ";
cin>>hck;     //enter the value assigned for iData or x
for(int i=0;i<5;i++)
{ptr++;
if(*ptr==hck)
{cout<<"Private data hacked...!!!\nChange the value : ";
cin>>*ptr;cout<<hck<<" Is chaged to : "<<*ptr;
return;}
}cout<<"Sorry value not found.....";
}
#define CONCATE_(X, Y) X##Y
#define CONCATE(X, Y) CONCATE_(X, Y)

#define ALLOW_ACCESS(CLASS, MEMBER, ...) \
  template<typename Only, __VA_ARGS__ CLASS::*Member> \
  struct CONCATE(MEMBER, __LINE__) { friend __VA_ARGS__ CLASS::*Access(Only*) { return Member; } }; \
  template<typename> struct Only_##MEMBER; \
  template<> struct Only_##MEMBER<CLASS> { friend __VA_ARGS__ CLASS::*Access(Only_##MEMBER<CLASS>*); }; \
  template struct CONCATE(MEMBER, __LINE__)<Only_##MEMBER<CLASS>, &CLASS::MEMBER>

#define ACCESS(OBJECT, MEMBER) \     
 (OBJECT).*Access((Only_##MEMBER<std::remove_reference<decltype(OBJECT)>::type>*)nullptr)
ALLOW_ACCESS(<class>, <member>, <type>);
ACCESS(<object>, <member>) = <value>;   // 1
auto& ref = ACCESS(<object>, <member>); // 2
struct X {
  int get_member () const { return member; };
private:
  int member = 0;
};

ALLOW_ACCESS(X, member, int);

int main() {
  X x;
  ACCESS(x, member) = 42;
  std::cout << "proof: " << x.get_member() << std::endl;
}
    struct A {
    A(): member(10){}
    private:
    int get_member() { return member;}
    int member;
   };

   typedef int (A::*A_fm_ptr)();
   A_fm_ptr  get_fm();

  template<   A_fm_ptr p> 
  struct Rob{ 
     friend A_fm_ptr  get_fm() {
   return p;
  }
};

 template struct Rob<  &A::get_member>;

 int main() {
   A a;
  A_fm_ptr p = get_fm();

    std::cout << (a.*p)() << std::endl;

  }
class Foo
{
  public:
    int pub = 35;

  private:
    int foo = 5;
    const char * secret = "private :)";
};
#include <iostream>
#include <fstream>
#include <string>
#include <regex>

#include "other.hpp"

unsigned long long getPrivOffset(
  const char * klass,
  const char * priv,
  const char * srcfile
){

  std::ifstream read(srcfile);
  std::ofstream write("fork.hpp");
  std::regex r ("private:");
  std::string line;
  while(getline(read, line))
    // make all of the members public
    write << std::regex_replace(line, r, "public:") << '\n';
  write.close();
  read.close();
  // find the offset, using the clone object
  std::ofstream phony("phony.cpp");
  phony << 
  "#include <iostream>\n"
  "#include <fstream>\n"
  "#include \"fork.hpp\"\n"
  "int main() {\n";
  phony << klass << " obj;\n";
  // subtract to find the offset, the write it to a file
  phony << 
  "std::ofstream out(\"out.txt\");\n out <<   (((unsigned char *) &(obj." 
<< priv << ")) -((unsigned char *)   &obj)) << '\\n';\nout.close();";
  phony << "return 0;\n}";
  phony.close();
  system(
    "clang++-7 -o phony phony.cpp\n"
    "./phony\n"
    "rm phony phony.cpp fork.hpp");
  std::ifstream out("out.txt");
  // read the file containing the offset
  getline(out, line);
  out.close();
  system("rm out.txt");
  unsigned long long offset = strtoull(line.c_str(), NULL, 10);
  return offset;
}


template <typename OutputType, typename Object>
OutputType hack(
  Object obj, 
  const char * objectname,
  const char * priv_method_name,
  const char * srcfile
  ) {
  unsigned long long o = getPrivOffset(
    objectname, 
    priv_method_name, 
    srcfile
  );
  return *(OutputType *)(((unsigned char *) (&obj)+o));
}
#define HACK($output, $object, $inst, $priv, $src)\
hack <$output, $object> (\
  $inst,\
  #$object,\
  $priv,\
  $src)

int main() {
  Foo bar;
  std::cout << HACK(
    // output type
    const char *, 
    // type of the object to be "hacked"
    Foo,
    // the object being hacked
    bar,
    // the desired private member name
    "secret",
    // the source file of the object's type's definition
    "other.hpp"
    ) << '\n';
  return 0;
}
#include <iostream>

#include "access/access.hpp"

struct foo {
 private:
  std::string name = "hello";
  int age = 27;
  void print() {}
};

using tag_foo_name = access::Tag<class foo_name>;
template struct access::Accessor<tag_foo_name, foo, decltype(&foo::name), &foo::name>;

int main() {
  foo f;
  
  // peek hidden data
  std::cout << access::get<tag_foo_name>(f) << '\n'; // "hello"
  
  // steal hidden data
  access::get<tag_foo_name>(f) = "lupin";
  std::cout << access::get<tag_foo_name>(f) << '\n'; // "lupin"
}