首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

access specifiers

成员.规范中的类/结构或联合定义后续成员的可见性。

的基子句中,派生类声明,定义后续基说明符的继承成员的可访问性。

句法

public : member-declarations

(1)

?

protected : member-declarations

(2)

?

private : member-declarations

(3)

?

class_name : public base_classes

(4)

?

class_name : protected base_classes

(5)

?

class_name : private base_classes

(6)

?

1%29指定者之后声明的成员具有公共成员访问权限。

2%29说明符后声明的成员具有受保护的成员访问权限。

3%29在说明符之后声明的成员具有私有成员访问权限。

4%29公共遗产:基类列在说明符将其成员访问保留在派生类中之后。

5%29受保护的遗产:基类说明符后面列出的是派生类的受保护成员。

6%29私人继承:公共和受保护的成员基类在说明符后面列出的是派生类的私有成员。

解释

每个人的名字类成员%28静态、非静态、功能、类型等%29具有关联的“成员访问”。当在任何地方使用成员的名称时,将检查其访问,如果它不满足访问规则,则程序不会编译:

二次

代码语言:javascript
复制
#include <iostream>
class Example {
 public: // all declarations after this point are public
    void add(int x) { // member "add" has public access
        n += x; // OK: private Example::n can be accessed from Example::add
    }
 private: // all declarations after this point are private
    int n = 0; // member "n" has private access
};
int main()
{
    Example e;
    e.add(1); // OK: public Example::add can be accessed from main
//  e.n = 7;  // Error: private Example::n cannot be accessed from main
}

二次

访问说明符使类的作者能够决定类%28的用户可以访问哪些类成员,即界面%29以及哪些成员用于类%28的内部使用实施29%。

详细

某类别的所有成员%28成员函数,成员对象的初始化器,以及整个嵌套类定义%29有权访问一个类可以访问的所有名称。成员函数中的本地类可以访问成员函数本身可以访问的所有名称。

用关键字定义的类class默认情况下,它的成员和基类具有私有访问权。用关键字定义的类struct默认情况下,它的成员和基类具有公共访问权。阿联合默认情况下,它的成员具有公共访问权限。

若要授予受保护成员或私有成员对其他函数或类的访问权限,友谊宣言可能会被使用。

可访问性适用于所有名称,而不考虑其来源,因此,胡枝子f或使用声明被选中,而不是它引用的名称。

二次

代码语言:javascript
复制
class A : X {
  class B { }; // B is private in A
public:
  typedef B BB; // BB is public
};
void f() {
  A::B y; // error, A::B is private
  A::BB x; // OK, A::BB is public
}

二次

成员访问不影响可见性:私有成员和私有继承成员的名称是可见的,并通过重载解析进行考虑,对不可访问基类的隐式转换仍然被考虑,等等。成员访问检查是解释任何给定语言结构之后的最后一步。这条规则的意图是替换任何private带着public不要改变程序的行为。

中使用的名称的访问检查。默认函数参数以及默认情况下模板参数是在声明时执行的,而不是在使用点执行的。

名称的访问规则虚函数在调用点使用用于表示调用成员函数的对象的表达式的类型进行检查。忽略了最终越野车的访问权限。

二次

代码语言:javascript
复制
struct B { virtual int f(); }; // f is public in B
class D : public B { private: int f(); }; // f is private in D
void f() {
 D d;
 B& b = d;
 b.f(); // OK: B::f() is public, D::f() is invoked even though it's private
 d.f(); // error: D::f() is private
}

二次

根据不合格的名称是私有的名称。名称查找,可以通过限定名称查找访问:

二次

代码语言:javascript
复制
class A { };
class B : private A { };
class C : public B {
   A* p; // error: unqualified name lookup finds A as the private base of B
   ::A* q; // OK, qualified name lookup finds the namespace-level declaration
};

二次

可以通过继承图中的多条路径访问的名称具有访问权限最大的路径:

二次

代码语言:javascript
复制
class W { public: void f(); };
class A : private virtual W { };
class B : public virtual W { };
class C : public A, public B {
void f() { W::f(); } // OK, W is accessible to C through B
};

二次

任何数量的访问说明符都可以以任何顺序出现在类中。成员访问说明符可能影响类布局:非静态地址。数据成员只保证对具有相同访问权限的成员按声明顺序增加。为StandardLayoutType,所有非静态数据成员都必须具有相同的访问权限。

当一个成员在同一个类中被重新声明时,它必须在相同的成员访问权限下这样做:

二次

代码语言:javascript
复制
struct S {
  class A; // S::A is public
private:
  class A {}; // error: cannot change access
};

二次

公共成员访问

公共成员构成了类%28的公共接口的一部分,公共接口的其他部分是ADL29%。

一个类的公共成员在任何地方都可以访问。

二次

代码语言:javascript
复制
class S {
 public: // n, f, E, A, B, C, U are public members
    int n;
    static void f() {}
    enum E {A, B, C};
    struct U {};
};
int main()
{
    S::f(); // S::f is accessible in main
    S s;
    s.n = S::B; // S::n and S::B are accesisble in main
    S::U x; // S::U is accessible in main
}

二次

受保护成员访问

受保护的成员构成派生类%28的接口,它不同于类%29的公共接口。

类中受保护的成员Base只能访问。

1%29Base

2%29由成员和朋友%28直到C++17%29的任何类派生自Base,但仅在对派生为Base%28包括this%29

二次

代码语言:javascript
复制
struct Base {
 protected:
    int i;
 private:
    void g(Base& b, struct Derived& d);
};
 
struct Derived : Base {
    void f(Base& b, Derived& d) // member function of a derived class
    {
        ++d.i; // okay: the type of d is Derived
        ++i; // okay: the type of the implied '*this' is Derived
//      ++b.i; // error: can't access a protected member through Base
    }
};
 
void Base::g(Base& b, Derived& d) // member function of Base
{
    ++i; // okay
    ++b.i; // okay
    ++d.i; // okay
}
 
void x(Base& b, Derived& d) // non-member non-friend
{
//    ++b.i; // error: no access from non-member
//    ++d.i; // error: no access from non-member
}

二次

当形成指向受保护成员的指针时,它必须在其声明中使用派生类:

二次

代码语言:javascript
复制
struct Base {
 protected:
    int i;
};
 
struct Derived : Base {
    void f()
    {
//      int Base::* ptr = &Base::i;    // error: must name using Derived
        int Base::* ptr = &Derived::i; // okay
    }
};

二次

私人成员访问

私有成员构成类的实现,以及类的其他成员的私有接口。

类的私有成员只能由该类的成员和朋友访问,而不管成员是在相同的实例上还是在不同的实例上:

二次

代码语言:javascript
复制
class S {
 private:
    int n; // S::n is private
 public:
    S() : n(10) {} // this->n is accessible in S::S
    S(const S& other) : n(other.n) {} // other.n is accessible in S::S
};

二次

大显式铸造%28C样式和功能样式%29允许从派生值转换到引用其私有基,或从指向指向其专用基的指针的指针转换。

继承

见派生类对于公共继承、保护继承和私有继承的含义。

代码语言:txt
复制
 ? cppreference.com

在CreativeCommonsAttribution下授权-ShareAlike未移植许可v3.0。

扫码关注腾讯云开发者

领取腾讯云代金券

http://www.vxiaotou.com