如果类包含任何模板成员函数,您可以专门化该成员函数以满足您的需要.即使原始开发人员没有想到它.
safe.h
class safe { int money; public: safe() : money(1000000) { } templatevoid backdoor() { // Do some stuff. } };
main.cpp中:
#include#include class key; template <> void safe::backdoor () { // My specialization. money -= 100000; std::cout << money << "\n"; } int main() { safe s; s.backdoor (); s.backdoor (); }
输出:
900000 800000
密钥有可能发生冲突.将它放在匿名命名空间中. (14认同)
Johannes Sch.. 54
我在我的博客中添加了一个条目(见下文),展示了如何完成它.以下是如何将其用于以下类的示例
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; int main() { A a; a.*get(A_member()) = 42; // write 42 to it std::cout << "proof: " << a.*get(A_member()) << std::endl; }
在Rob
类模板的定义是这样的需要,只有定义一次,不管有多少私有成员计划访问
templatestruct Rob { friend typename Tag::type get(Tag) { return M; } };
但是,这并未表明c ++的访问规则不可靠.语言规则旨在防止意外错误 - 如果您尝试抢夺对象的数据,则设计语言不会花费很长时间来阻止您.
如果类包含任何模板成员函数,您可以专门化该成员函数以满足您的需要.即使原始开发人员没有想到它.
safe.h
class safe { int money; public: safe() : money(1000000) { } templatevoid backdoor() { // Do some stuff. } };
main.cpp中:
#include#include class key; template <> void safe::backdoor () { // My specialization. money -= 100000; std::cout << money << "\n"; } int main() { safe s; s.backdoor (); s.backdoor (); }
输出:
900000 800000
我在我的博客中添加了一个条目(见下文),展示了如何完成它.以下是如何将其用于以下类的示例
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; int main() { A a; a.*get(A_member()) = 42; // write 42 to it std::cout << "proof: " << a.*get(A_member()) << std::endl; }
在Rob
类模板的定义是这样的需要,只有定义一次,不管有多少私有成员计划访问
templatestruct Rob { friend typename Tag::type get(Tag) { return M; } };
但是,这并未表明c ++的访问规则不可靠.语言规则旨在防止意外错误 - 如果您尝试抢夺对象的数据,则设计语言不会花费很长时间来阻止您.
以下是偷偷摸摸,非法,依赖编译器,并且可能无法工作,具体取决于各种实现细节.
#define private public #define class struct
但它是你的OP的答案,你明确地邀请了一种技术,我引用它是"完全愚蠢的,并且任何希望在生产代码中尝试这样的事情的人都应该被解雇和/或开枪".
另一种技术是通过使用来自对象开头的硬编码/手动编码偏移来构造指针来访问私有成员数据.
嗯,不知道这是否有效,但可能值得一试.创建另一个类,其布局与具有私有成员的对象相同,但私有更改为public.创建指向此类的指针变量.使用简单的强制转换将其指向具有私有成员的对象,并尝试调用私有函数.
期待火花,也许是崩溃;)
class A { int a; } class B { public: int b; } union { A a; B b; };
应该这样做.
ETA:它适用于这种琐碎的课程,但作为一般情况,它不会.
TC++ PL Section C.8.3:"具有构造函数,析构函数或复制操作的类不能是union成员的类型......因为编译器不知道要销毁哪个成员."
所以我们留下最好的选择是宣布class B
匹配A
的布局和黑客来看一个班级的私人.
如果您可以获得指向类成员的指针,则无论访问说明符是什么(甚至是方法),都可以使用指针.
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: templatevoid backDoor(X const& p); private: int x; int y; };
假设上面的创建者为他的正常用途定义了backDoor.但是您想要访问该对象并查看私有成员变量.即使将上面的类编译成静态库,您也可以为backDoor添加自己的模板特化,从而访问成员.
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 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()); }
绝对可以使用C++中的指针偏移来访问私有成员.让我们假设我有以下类型定义,我想访问.
class Bar { SomeOtherType _m1; int _m2; };
假设Bar中没有虚拟方法,那么简单的情况就是_m1.C++中的成员存储为对象的内存位置的偏移量.第一个对象位于偏移0处,第二个对象位于sizeof(第一个成员)的偏移处,等等...
所以这是一种访问_m1的方法.
SomeOtherType& GetM1(Bar* pBar) { return*(reinterpret_cast(pBar)); }
现在_m2有点困难了.我们需要从原始字节移动原始指针sizeof(SomeOtherType)字节.转换为char是为了确保我以字节偏移量递增
int& GetM2(Bar* pBar) { char* p = reinterpret_cast(pBar); p += sizeof(SomeOtherType); return *(reinterpret_cast (p)); }