Friend函数访问静态库中定义的类的私有成员

Friend function access the private members of class defined in static library

本文关键字:成员 定义 函数 访问 静态 Friend      更新时间:2023-10-16

我有一个用C++编写的静态库。我还得到了静态库中定义的类的头文件。

我可以访问在类声明中引入友元函数的静态库中定义的类的私有成员吗?

您的意思是要更改库附带的头文件?不能保证在那里添加friend声明会起作用。您可能会弄乱链接部分,即使您的编译器说可以。

此外,如果这些成员是private,则不能访问它们。

从技术上讲,使用不同的令牌序列以不同的翻译单位定义同一实体(此处为类)是未定义的行为

无论你使用什么技术,只要它改变了构成它的令牌的顺序,从标准的角度来看,它都是邪恶的(尽管在实践中可能有效)。

约翰内斯发现了一种在尊重标准的同时做到这一点的方法。这是基于这样一个事实,即即使a是类A中的私有属性,&A::a也可以在不能写入A.a的上下文中写入(可能是标准中的疏忽?)。

核心方法:

template<typename Tag, typename Tag::type M>
struct Rob { 
  friend typename Tag::type get(Tag) {
    return M;
  }
};
// use
struct A {
  A(int a):a(a) { }
private:
  int a;
};
// tag used to access A::a
struct A_f { 
  typedef int A::*type;
  friend type get(A_f);
};
template struct Rob<A_f, &A::a>;
int main() {
  A a(42);
  std::cout << "proof: " << a.*get(A_f()) << std::endl;
}

简化扩展:

template<typename Tag, typename Member>
struct TagBase {
  typedef Member type;
  friend type get(Tag);
};
struct A_f : TagBase<A_f, int A::*> { };

编辑

这个技巧(有趣的是)被标准明确允许

§14.7.2/12通常的访问检查规则不适用于用于指定显式实例化的名称。[…]