Rup*_*ick 10 c++ inheritance protected language-lawyer
任何人都可以向我解释为什么(例如,"为什么语言是这样的?")以下代码在第二行有编译错误B::C::bar?
class A
{
public:
struct D
{
void call_foo (A &a)
{
a.foo ();
}
};
protected:
void foo () {}
};
class B : public A
{
struct C : public A::D
{
void bar (A &a, B &b)
{
b.foo (); // OK
a.foo (); // Error. Huh?
call_foo (a); // Ugly workaround
}
};
};
Run Code Online (Sandbox Code Playgroud)
当且仅当基指针的类型恰好是封闭类型(而不是某些父类型)时,似乎方法可以安全地在父类中使用受保护的方法.
这看起来很奇怪.为什么这种语言呢?
结构C嵌套在类中B,它被注册为成员,因此它具有与任何其他成员相同的访问权限.所以是的,它可以访问protected基类的成员A.但请注意,您只能通过类型对象访问protected成员; 你不能通过一个.这是有道理的,因为派生类的成员应该只能访问从基类继承的成员; 这些成员属于派生类.但是不应该允许直接访问基类的成员; 它们属于基类(或其他派生类).ABAprotectedprotected
规则对于内部类并不特殊,对于成员函数也是如此B.
§11.4/ 1受保护的成员访问[class.protected]
(强调我的)
当非静态数据成员或非静态成员函数是其命名类([class.access.base])的受保护成员时,将应用超出前面在Clause [class.access]中描述的那些的附加访问检查.115如上所述之前,授予对受保护成员的访问权限,因为引用发生在某个C类的朋友或成员中.如果访问要形成指向成员的指针([expr.unary.op]),则嵌套名称说明符应表示C或从C派生的类.所有其他访问涉及(可能是隐式的)对象表达式([expr] .REF]).在这种情况下,对象表达式的类应为C或从C派生的类.[例如:
Run Code Online (Sandbox Code Playgroud)class B { protected: int i; static int j; }; class D1 : public B { }; class D2 : public B { friend void fr(B*,D1*,D2*); void mem(B*,D1*); }; ... void D2::mem(B* pb, D1* p1) { pb->i = 1; // ill-formed p1->i = 2; // ill-formed i = 3; // OK (access through this) B::i = 4; // OK (access through this, qualification ignored) int B::* pmi_B = &B::i; // ill-formed int B::* pmi_B2 = &D2::i; // OK j = 5; // OK (because j refers to static member) B::j = 6; // OK (because B?::?j refers to static member) } ...- 结束例子]