前情提要
当然,本文不讨论基本的友元破封装的套路。
访问的私有函数是一个虚函数
虚函数可以通过虚表的地址算出来。
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| #include <QCoreApplication> #include <iostream>
class Test { private: virtual void func() { std::cout << __func__ << std::endl; } virtual void func2() { std::cout << __func__ << std::endl; } };
int main(int argc, char *argv[]) { QCoreApplication a(argc, argv);
Test t; unsigned int v_table_addr = *((unsigned int *) &t); typedef void (*pFunc)(void *); pFunc func = (pFunc)(*((unsigned int *)v_table_addr)); func(&t); pFunc func2 = (pFunc)(*((unsigned int *)(v_table_addr + 4))); func2(&t);
return a.exec(); }
|
访问的私有函数是普通函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
|
#include <iostream>
template<typename Tag> struct result { 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> { 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 A { private: void func() { std::cout << __func__ << std::endl; } void func2(int n) { std::cout << __func__ << n << std::endl; } };
struct Af { typedef void(A::*type)(); }; template class rob<Af, &A::func>;
struct Af2 { typedef void(A::*type)(int); }; template class rob<Af2, &A::func2>;
int main() { A a; (a.*result<Af>::ptr)(); (a.*result<Af2>::ptr)(4); return 0; }
|
在Qt中访问私有槽函数
基于Qt的元对象系统,可以通过QMetaObject::invokeMethod唤起。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| #include <QCoreApplication> #include <iostream>
class Test: public QObject { Q_OBJECT public: Test(QObject *parent = nullptr) : QObject(parent) {} private slots: void func() { std::cout << __func__ << std::endl; } };
#include "main.moc"
int main(int argc, char *argv[]) { QCoreApplication a(argc, argv);
Test t; QMetaObject::invokeMethod(&t, "func");
return a.exec(); }
|