指向成员的指针可能绕过成员的访问级别
May pointer to members circumvent the access level of a member?
我们臭名昭著的litb有一篇关于如何规避访问检查的有趣文章。
这个简单的代码充分证明了这一点:
#include <iostream>
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;
}
它使用gcc 4.3.4、gcc 4.5.1、gcc 4.7.0编译和运行(输出42
)(请参阅用户1131467的评论),并在C++03严格模式和MSVC 2005中使用Clang 3.0和Comeau C/C++4.3.10.1编译。
Luchian问我这个答案,我用它来证明它实际上是合法的。我同意Luchian的观点,认为这很奇怪,但Clang和Comeau都是可用的大多数"标准"编译器的有力竞争者(默认情况下比MSVC更重要)。。。
我在我现有的标准草案中找不到任何东西(n3337是我拿到的最后一个版本)。
所以。。。有人真的能证明它是否合法吗?
是的,这是合法的。相关文本见§14.7.2/12,讨论了显式模板实例化:
12通常的访问检查规则不适用于用于指定显式实例化的名称。[注意:特别是,函数声明符中使用的模板参数和名称(包括参数类型、返回类型和异常规范)可能是通常不可访问的私有类型或对象,模板可能是通常不会访问的成员模板或成员函数可访问。--尾注]
埃姆帕西斯矿。
该代码显然是非法的(并且需要编译时诊断)。行中:
template struct Rob<A_f, &A::a>;
表达式CCD_ 2访问CCD_。
标准对此非常明确:;应用访问控制统一到所有名称,无论这些名称是从声明或表达式“(§11/4,增加了重点)。由于a
在A
中是私有名称,因此在A
之外对它的任何引用都是非法的。
相关文章:
- 固有构造函数的字符和访问级别
- 这是关于成员访问规则的正确摘要吗
- 为什么我在空指针错误(链表)中获取成员访问权限
- 成员访问是否在空指针上定义C++?
- C++ IDE 不会推断/自动完成对模板类中的 std::array 下标表达式的成员访问
- 为什么类成员数据必须是静态的才能被模板化类的模板化结构成员访问
- 为什么c++允许成员函数定义中实例的私有成员访问
- C/C++ 包含点的宏参数(成员访问运算符)
- 访问说明符(私有/公共/受保护)如何在内部工作(限制成员访问)?
- 如何将超类的受保护成员访问到其派生类. 如果已在派生类中声明了具有相同名称的函数?
- 内部类私有成员访问和封闭的友好性
- 通过 C++ 中的另一个结构成员访问结构
- 具体化 PRVALUES 成员访问的 decltype 行为不正确
- 常量表达式中的静态成员访问
- XVALUE来自类成员访问表达式
- 未经授权的私有类成员访问会产生编译时错误而不是运行时错误?
- 在 c++ 中,为什么 -> 被称为二进制中缀指针成员访问运算符?
- 如何访问模板参数的成员?“成员访问不完整的类型”
- 成员功能模板专业化是否可以具有与主模板不同的访问级别
- 指向成员的指针可能绕过成员的访问级别