
这个技巧首次由 Johannes Schaublitb在 2010 年的一篇文章 Access to private members. Thats easy! 中提出。首先需要搞懂几个概念模板的概念特别模板显示实例化template typename T struct X { ... }; // 主模板 template typename T struct XT* { ... }; // 偏特化 template struct Xint { ... }; // 显式全特化 template struct Xint; // 显式实例化 ★ Xint obj; // 隐式实例化 extern template struct Xint; // 显式实例化声明抑制隐式实例化直接给案例我也没看懂#include iostream // 目标类有私有成员 class Victim { private: int secret_ 42; void sayHi() { std::cout Hi, secret secret_ \n; } }; // 通用 Rob 模板 // Tag 是一个空标签类型用来区分不同的被偷成员 // Tag::type 是被偷成员的成员指针类型 // M 是那个成员指针的具体值作为非类型模板参数传入 template typename Tag, typename Tag::type M struct Rob { // friend 函数定义在这里定义 get(Tag)返回成员指针 M // 注意这个 friend 函数的定义只有当 Rob 被实例化时才产生 friend typename Tag::type get(Tag) { return M; } }; // 为 secret_ 定义一个 Tag struct Victim_secret { using type int Victim::*; // 数据成员指针类型 friend type get(Victim_secret); // 声明 friend 函数无定义 }; // 显式实例化 Rob触发 friend 函数 get(Victim_secret) 的定义 // 这一行是关键Victim::secret_ 作为模板参数在此上下文中不做访问检查 template struct RobVictim_secret, Victim::secret_; // 为 sayHi 定义一个 Tag struct Victim_sayHi { using type void (Victim::*)(); // 成员函数指针类型 friend type get(Victim_sayHi); }; template struct RobVictim_sayHi, Victim::sayHi; // 使用 int main() { Victim v; // 偷数据成员 auto secretPtr get(Victim_secret{}); // 得到 int Victim::* std::cout secret v.*secretPtr \n; // 读 v.*secretPtr 100; // 写 std::cout secret v.*secretPtr \n; // 偷成员函数 auto sayHiPtr get(Victim_sayHi{}); (v.*sayHiPtr)(); // 调用私有函数 return 0; }