[英]why c++ allows pointers if they can generate problems like accessing private members?
[英]Why this code allows accessing private variables
几天前,我遇到了这种方法(作为C ++课程中编程任务的解决方案之一)。
#include <iostream>
struct C {
C(int i) { m_i = i; }
private:
int m_i;
};
template<typename Tag, int C::* M>
struct Rob {
friend
int C::* get(Tag) {
return M;
}
};
template<typename D>
struct AcessorTag {
typedef D C::*type;
};
template struct Rob<AcessorTag<int>, &C::m_i>;
int &get_c(C &cls) {
return cls.*get(AcessorTag<int>());
}
int main()
{
C c(13);
std::cout << get_c(c);
return 0;
}
您能否解释一下为什么编译此代码? 这里发生的几乎所有事情是:1)我们将指针指向成员作为结构模板的参数传递给我们; 2)声明一个朋友函数,该函数仅将该指针返回给成员。
这是标准的C ++吗? (我已经在VS 2015上进行了测试)
get
函数是struct Rob<>
的朋友,但不是struct C
。 无论如何, struct C
似乎没有朋友,那么为什么它的私有成员可以访问?
谢谢!
除了缺少get
函数的前向声明外,此代码还可以正常工作并且符合标准。 由于适用于模板的显式实例化定义的特殊规则,因此可以使用此代码:
17.8.2显式实例化[temp.explicit]
14通常的访问检查规则不适用于用于指定显式实例化的名称。 [注:特别是,函数声明符中使用的模板参数和名称(包括参数类型,返回类型和异常规范)可能是私有类型或对象,通常是无法访问的,并且模板可能是成员模板或成员函数通常是无法访问的。 —尾注]
所以写
template struct Rob<AcessorTag<int>, &C::m_i>;
将绕过常规的访问检查,并提供指向否则无法访问的成员的指针,以get
函数体。
当然,您的代码无法使用gnu c ++和clang ++进行编译; 标识符get
不是C
的成员。 即使您尝试实例化Rob
,例如
Rob<AcessorTag<int>, &C::m_i> rob;
您获得
error: 'int C::m_i' is private.
您可以随时询问Microsoft他们的c ++编译器是否符合任何标准。 如果他们完全回答,请告诉我他们的答案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.