Friend函数访问静态库中定义的类的私有成员
Posted
技术标签:
【中文标题】Friend函数访问静态库中定义的类的私有成员【英文标题】:Friend function access the private members of class defined in static library 【发布时间】:2012-04-11 19:42:50 【问题描述】:我有一个用 C++ 编写的静态库。我还得到了静态库中定义的类的头文件。
我可以访问在类声明中引入友元函数的静态库中定义的类的私有成员吗?
【问题讨论】:
魔鬼使用:#define private public
不错 :).......但这不会每次都有效
@smerlin:我会避免这种情况。从法律角度来看,这本身就是未定义的行为,因为private
是一个保留标识符(编译器可能会产生错误并拒绝编译或默默地忽略您的指令)。其次,类的布局取决于成员的访问级别。虽然这是一个很少使用的功能,但您可能会通过让程序的不同部分为同一对象期望不同的内存布局来引入细微的错误。
【参考方案1】:
您的意思是要更改库附带的标头?不能保证在那里添加 friend
声明会起作用。你可能搞砸了链接部分,即使你的编译器说没问题。
另外,如果这些成员是 private
,您就不能访问它们。
【讨论】:
您能否详细说明:如何它可能是个问题? @Als 我在 Visual Studio 上尝试过类似的东西。我自己编辑了标题并将私有替换为公共,并且我得到了未解决的外部。 可能在 gcc 上不是问题,但我很确定在构建库后修改标头不是一个好主意。 @Luchian : 有没有试过在类声明中引入友元函数,看看能不能访问私有成员? @nsit_poison 我已经告诉过你它可以编译,但这并不正确。 @nsit_poison 如果未定义,则不是漏洞。【参考方案2】:使用不同的标记序列在不同的翻译单元中定义相同的实体(这里是一个类)在技术上是未定义的行为。
无论你使用什么技术,只要它改变了组成它的标记的顺序,从标准的角度来看,它就是邪恶的(尽管可能在实践中起作用)。
Johannes discovered a way 在遵守标准的同时这样做。它基于这样一个事实,即使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::*> ;
编辑:
这个技巧(有趣地)是标准的explicitly allowed
§14.7.2/12 通常的访问检查规则不适用于用于指定显式实例化的名称。 [...]
【讨论】:
我对帖子很熟悉,但&A::a
仍然不合法。至少我不这么认为。在 MSVS 下它无法编译,当我要求他提供标准报价时,他没有提供报价,所以我对这个解决方案持保留态度。 ***.com/a/6886432/673730
@LuchianGrigore:我很乐意检查,但我什至无法在标准中找到描述语法 &A::a
的参考。 指向成员的指针 只产生一些引用...您知道要使用的术语或描述的语法在哪里吗?
我不知道,但我怀疑你会发现说它是合法的。实际上,您正在尝试获取私人成员的地址。看不出标准如何或为什么允许这样做。
@LuchianGrigore:好吧,我决定把SO community on this issue。希望有人会在标准中找到关于它是否真的被允许的线索......以上是关于Friend函数访问静态库中定义的类的私有成员的主要内容,如果未能解决你的问题,请参考以下文章