总结C ++中的成员访问规则

问题描述 投票:2回答:1

我试图完全理解C ++标准[class.access]部分的多个段落中定义的成员访问规则。它们相当complex or even confusing,因此我需要简短但准确而详尽的摘要

我编译了[[1]]该程序在多种情况下测试受保护成员的可访问性(因为受保护成员的规则最复杂):#include <iostream> class B { protected: int i = 1; static int const I = 1; }; class X: public B { protected: int j = 2; static int const J = 2; public: void f(); friend void g(); }; class D: public X { protected: int k = 3; static int const K = 3; }; void X::f() { B b; X x; D d; //std::cout << b.i; // error: 'i' is a protected member of 'B' std::cout << b.I; std::cout << x.i; std::cout << x.I; std::cout << x.j; std::cout << x.J; std::cout << d.i; std::cout << d.I; std::cout << d.j; std::cout << d.J; //std::cout << d.k; // error: 'k' is a protected member of 'D' //std::cout << d.K; // error: 'K' is a protected member of 'D' } void g() { B b; X x; D d; //std::cout << b.i; // error: 'i' is a protected member of 'B' //std::cout << b.I; // error: 'I' is a protected member of 'B' std::cout << x.i; std::cout << x.I; std::cout << x.j; std::cout << x.J; std::cout << d.i; std::cout << d.I; std::cout << d.j; std::cout << d.J; //std::cout << d.k; // error: 'k' is a protected member of 'D' //std::cout << d.K; // error: 'K' is a protected member of 'D' } int main() { B b; X x; D d; //std::cout << b.i; // error: 'i' is a protected member of 'B' //std::cout << b.I; // error: 'I' is a protected member of 'B' //std::cout << x.i; // error: 'i' is a protected member of 'B' //std::cout << x.I; // error: 'I' is a protected member of 'B' //std::cout << x.j; // error: 'j' is a protected member of 'X' //std::cout << x.J; // error: 'J' is a protected member of 'X' //std::cout << d.i; // error: 'i' is a protected member of 'B' //std::cout << d.I; // error: 'I' is a protected member of 'B' //std::cout << d.j; // error: 'j' is a protected member of 'X' //std::cout << d.J; // error: 'J' is a protected member of 'X' //std::cout << d.k; // error: 'k' is a protected member of 'D' //std::cout << d.K; // error: 'K' is a protected member of 'D' return 0; }

我在

direct

可访问性方面得出了这个结论:2类的
  • 公共成员可供任何实体直接访问(参见[class.access/base-5.1]);班级的[[私人成员
  • 仅该班级的成员和朋友可以直接访问(参见[class.access/base-5.2]);类别的[[
  • 受保护的成员
  • 仅该类别的成员和朋友(请参阅[class.access/base-5.3]),该类别的基本类别的成员和朋友可以直接访问(如果这些受保护的成员是从那些基类或这些基类的基类(cf. [class.access/base-5.4]),
  • 3继承,并继承到该类的derived classes
的成员(cf. [class.access/base-5.3])(如果受保护)成员既不是非静态数据成员也不是非静态成员函数(参见[class.access/class.protected-1])。我的摘要准确无误吗?

1

我在C ++ 17中使用了Clang 9.0.0编译器。

2

对类成员的访问可以是直接的,即通过该类的访问(direct access),也可以是间接的,即通过该类的派生类的访问(

继承访问

)。由于从派生类继承的成员可以从执行访问的实体的角度(在[class.access/base-1]中指定的可访问性发生变化)的角度被视为派生类的成员of,因此对类成员的继承访问可以被同化以直接访问该类的派生类的继承成员。换句话说,仅需要考虑直接访问3我的条款在这里与标准[class.access/base-5.4]的引用条款略有不同:

如果在类N中被命名,则成员R在点R是可访问的

  • 存在一个在N处可访问的N的基类B,当在类B中命名时,m在R处可访问。
  • 这是因为编译器的行为有所不同,我的感觉是编译器是正确的。我认为标准的条款有两个问题:
  • 访问点R应该限制为B类的成员和朋友(这是编译器通过在程序的d.*中引发对main访问的错误而执行的操作;

    应该将N类中的成员m限制为从B类继承,而不是被N类覆盖(这是编译器将通过引发d.id.Id.j和[如果您在程序的d.J中覆盖了X::fgiI,则C0]将访问jJ

    • 我试图完全理解C ++标准[class.access]节的多个段落中定义的成员访问规则。它们非常复杂,甚至令人困惑,因此我需要一个简短的...
    c++ language-lawyer protected access-specifier
    1个回答
    0
    投票

      public
    © www.soinside.com 2019 - 2024. All rights reserved.