YSC*_*YSC 52 c++ protected access-specifier member-pointers language-lawyer
我们都知道protected从基类指定的成员只能从派生类自己的实例访问.这是标准的一个特性,这已在Stack Overflow上多次讨论:
但似乎有可能用成员指针来解决这个限制,因为用户chtz 向我展示:
struct Base { protected: int value; };
struct Derived : Base
{
void f(Base const& other)
{
//int n = other.value; // error: 'int Base::value' is protected within this context
int n = other.*(&Derived::value); // ok??? why?
(void) n;
}
};
Run Code Online (Sandbox Code Playgroud)
为什么这可能,它是一个想要的功能或实施中的某个地方或标准的措辞?
从评论中出现了另一个问题:如果Derived::f用实际调用Base,是不确定的行为?
Oli*_*liv 30
由于访问控制[class.access],使用类成员访问 expr.ref(aclass.amember)无法访问成员的事实不会使此成员无法使用其他表达式访问.
表达式&Derived::value (其类型为int Base::*)是完全符合标准的,它指定构件value的Base.然后表达式a_base.*pwhere p指向成员Base和a_base实例的指针Base也是标准兼容的.
因此,任何符合标准的编译器必须使表达式other.*(&Derived::value);定义的行为:访问会员value的other.
eer*_*ika 15
这是一个黑客?
与使用类似reinterpret_cast,这可能是危险的,并且可能是很难找到错误的来源.但它的形成良好,毫无疑问它是否应该有效.
澄清类比:行为reinterpret_cast也完全在标准中指定,可以在没有任何UB的情况下使用.但reinterpret_cast绕过类型系统,类型系统是有原因的.类似地,这个指向成员技巧的指针很好地根据标准形成,但它绕过成员的封装,并且封装(通常)存在是有原因的(我通常说,因为我认为程序员可以轻率地使用封装).
[是]在执行中的某个地方还是标准的措辞?
不,实施是正确的.这是指定语言的工作方式.
成员函数Derived可以明显访问&Derived::value,因为它是一个受保护的成员基础.
该操作的结果是指向成员的指针Base.这可以应用于参考Base.成员访问权限不适用于指向成员的指针:它仅适用于成员的名称.
从评论中出现了另一个问题:如果使用实际Base调用Derived :: f,它是否是未定义的行为?
不是UB.Base有会员.