外部函数如何访问其它类的私有成员,你可能想到的是友元,然而友元会侵入原class的代码。
今天看到一个黑魔法:
class Bank {
private:
double money = 999;
public:
void check() {
std::cout << "check:" << money << "\n";
}
};
template<auto M>
struct Tunnel;
template<class T, class U, T U::*M>
struct Tunnel<M> {
friend T& sneak(U& u) {
return u.*M;
}
};
template struct Tunnel<&Bank::money>;
double& sneak(Bank&);
int main() {
Bank bank;
bank.check();
auto& take_control = sneak(bank);
auto booty = take_control;
take_control = 0.114514;
std::cout << "booty: " << booty << "\n";
bank.check();
}
这个黑魔法的原理是C++可以显式实例化模板类,而显式实例化包括私有成员指针的特化。但这样还不够,即使显式实例化了,取不到私有成员的指针还是会调用不到这个特化。然而,C++有一个东西叫友元(friend),它除了可以让友元函数访问私有成员,还可以为该函数提供定义。这样一来,在友元函数的定义中使用模板参数(私有成员指针)访问私有成员,在外面不需要取得私有成员指针也能调用该友元函数。
来源:https://www.zhihu.com/question/521898260/answer/2394522797
还有个此黑魔法的开源库,用于访问类的私有成员很方便,看下使用代码:
class A {
int m_i = 3;
};
ACCESS_PRIVATE_FIELD(A, int, m_i)
void foo() {
A a;
auto &i = access_private::m_i(a);
assert(i == 3);
}
这个开源库的地址在:https://github.com/martong/access_private
有兴趣的朋友可以研究研究。
这里有 一个优质的C++学习圈 等你加入。