在C ++中调用私有方法
这纯粹是一个理论问题,我知道如果有人宣称某种方法是私人的,那么你可能不应该这么叫。 我设法调用私有虚拟方法和更改私人成员的实例,但我不知道如何调用一个私人的非虚拟方法(不使用__asm
)。 有没有办法获得指针的方法? 还有其他的方法吗?
编辑:我不想改变类的定义! 我只想要一个黑客/解决方法。 🙂
#include
头文件,但:
#define private public #define class struct
显然你需要绕过各种包容卫士等,并在一个孤立的编译单位做这个。
编辑:仍然hackish,但更less如此:
#include <iostream> #define private friend class Hack; private class Foo { public: Foo(int v) : test_(v) {} private: void bar(); int test_; }; #undef private void Foo::bar() { std::cout << "hello: " << test_ << std::endl; } class Hack { public: static void bar(Foo& f) { f.bar(); } }; int _tmain(int argc, _TCHAR* argv[]) { Foo f(42); Hack::bar(f); system("pause"); return 0; }
看我的博客文章 。 我在这里重新发布代码
template<typename Tag> struct result { /* export it ... */ typedef typename Tag::type type; static type ptr; }; 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; }; template<typename Tag, typename Tag::type p> typename rob<Tag, p>::filler rob<Tag, p>::filler_obj;
有私人会员的class级
struct A { private: void f() { std::cout << "proof!" << std::endl; } };
以及如何访问它们
struct Af { typedef void(A::*type)(); }; template class rob<Af, &A::f>; int main() { A a; (a.*result<Af>::ptr)(); }
如果public
函数返回private
函数的地址,则可以调用该函数,然后任何人都可以使用该地址来调用私有函数。
例,
class A { void f() { cout << "private function gets called" << endl; } public: typedef void (A::*pF)(); pF get() { return &A::f; } }; int main() { A a; void (A::*pF)() = a.get(); (a.*pF)(); //it invokes the private function! }
输出:
private function gets called
在ideone演示: http : //www.ideone.com/zkAw3
从同一个类的公共函数调用私有方法。
你有朋友的课程和function。
我知道,如果有人宣布一个私人的方法,你可能不应该叫它。
关键不是“你不应该这么称呼”,而是“你不能称之为”。 你究竟想要做什么?
最简单的方法是:
#define private public #define protected public
跟进TED的回答:不要编辑标题。 相反,创build自己的标题的私人副本,并插入一些friend
声明在标题的副本。 在你的来源中, #include
这个伪造的标题,而不是真正的标题。 瞧!
将private改为public可能会改变由内联方法产生的弱符号,而这又可能导致链接器投诉。 如果所做的只是添加一些朋友声明,那么由内联方法产生的弱符号将具有与假冒和真实头部相同的签名。 通过这些朋友声明,你现在可以在课堂上做各种各样的恶事,比如访问私人数据和打私人成员。
附录
如果问题标题使用#pragma once
而不是#include
guard来确保标题是幂等的,则此方法将不起作用。
那么,显而易见的方法是编辑代码,使其不再是私人的。
如果你坚持find一个邪恶的方式来做到这一点……以及一些编译器可能会创build自己的头文件版本,其中一种方法是public
而不是private
。 邪恶有一个讨厌的方式反弹在你身上(这就是为什么我们称之为“邪恶”)。
我认为最接近黑客的是这个 ,但这不仅是不明智的,但是没有定义的行为,所以它没有语义。 如果碰巧以任何单一程序调用的方式运行,那么这就是纯粹的机会。
定义一个与公开function相同的类。
然后用私有函数将一个对象与公共函数绑定到一个对象,然后调用公共函数。
如果我们谈到MSVC,我认为最简单的方法是除了调用私有方法本身之外没有其他伤害,这是非常棒的__asm:
class A { private: void TestA () {}; }; A a; __asm { // MSVC assumes (this) to be in the ecx. // We cannot use mov since (a) is located on the stack // (ie [ebp + ...] or [esp - ...]) lea ecx, [a] call A::TestA }
对于GCC,可以通过使用函数的名称来完成。
#include <stdio.h> class A { public: A() { f(); //the function should be used somewhere to force gcc to generate it } private: void f() { printf("\nf"); } }; typedef void(A::*TF)(); union U { TF f; size_t i; }; int main(/*int argc, char *argv[]*/) { A a; //af(); //error U u; //uf = &A::f; //error //load effective address of the function asm("lea %0, _ZN1A1fEv" : "=r" (ui)); (a.*uf)(); return 0; }
有问题的名字可以通过nm * .o文件find。
添加-masm = intel编译器选项
来源: GCC错误:无法将offsetof应用于成员函数MyClass :: MyFunction https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html