关于c ++:什么是访问说明符?

What are access specifiers? Should I inherit with private, protected or public?

我对访问修饰符对于继承的意义感到困惑。涉及privateprotectedpublic关键字的继承有什么区别?


什么是访问说明符?

对于C++中的类/结构/尤宁,有3个access specifiers。这些访问说明符定义如何访问类的成员。当然,类的任何成员都可以在该类中访问(在同一类的任何成员函数中)。接下来是访问说明符的类型,它们是:

public-声明为public的成员可以通过类的对象从类外部访问。

protected-声明为protected的成员可以从类外部访问,但只能在派生自该类的类中访问。

私有-这些成员只能从类内访问。不允许外部访问。

源代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class MyClass
{
    public:
        int a;
    protected:
        int b;
    private:
        int c;
};

int main()
{
    MyClass obj;
    obj.a = 10;     //Allowed
    obj.b = 20;     //Not Allowed, gives compiler error
    obj.c = 30;     //Not Allowed, gives compiler error
}

继承和访问说明符

C++中的继承可以是下列类型之一:

  • Private继承
  • Public继承
  • Protected继承

以下是与以下各项相关的成员访问规则:

First and most important rule Private members of a class are never accessible from anywhere except the members of the same class.

号公共继承:

All Public members of the Base Class become Public Members of the derived class &
All Protected members of the Base Class become Protected Members of the Derived Class.

也就是说,成员的访问权没有变化。我们之前讨论过的访问规则将进一步应用于这些成员。

代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Class Base
{
    public:
        int a;
    protected:
        int b;
    private:
        int c;
};

class Derived:public Base
{
    void doSomething()
    {
        a = 10;  //Allowed
        b = 20;  //Allowed
        c = 30;  //Not Allowed, Compiler Error
    }
};

int main()
{
    Derived obj;
    obj.a = 10;  //Allowed
    obj.b = 20;  //Not Allowed, Compiler Error
    obj.c = 30;  //Not Allowed, Compiler Error

}

号私有继承:

All Public members of the Base Class become Private Members of the Derived class &
All Protected members of the Base Class become Private Members of the Derived Class.

代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
Class Base
{
    public:
      int a;
    protected:
      int b;
    private:
      int c;
};

class Derived:private Base   //Not mentioning private is OK because for classes it  defaults to private
{
    void doSomething()
    {
        a = 10;  //Allowed
        b = 20;  //Allowed
        c = 30;  //Not Allowed, Compiler Error
    }
};

class Derived2:public Derived
{
    void doSomethingMore()
    {
        a = 10;  //Not Allowed, Compiler Error, a is private member of Derived now
        b = 20;  //Not Allowed, Compiler Error, b is private member of Derived now
        c = 30;  //Not Allowed, Compiler Error
    }
};

int main()
{
    Derived obj;
    obj.a = 10;  //Not Allowed, Compiler Error
    obj.b = 20;  //Not Allowed, Compiler Error
    obj.c = 30;  //Not Allowed, Compiler Error

}

受保护的继承:

All Public members of the Base Class become Protected Members of the derived class &
All Protected members of the Base Class become Protected Members of the Derived Class.

代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
Class Base
{
    public:
        int a;
    protected:
        int b;
    private:
        int c;
};

class Derived:protected Base  
{
    void doSomething()
    {
        a = 10;  //Allowed
        b = 20;  //Allowed
        c = 30;  //Not Allowed, Compiler Error
    }
};

class Derived2:public Derived
{
    void doSomethingMore()
    {
        a = 10;  //Allowed, a is protected member inside Derived & Derived2 is public derivation from Derived, a is now protected member of Derived2
        b = 20;  //Allowed, b is protected member inside Derived & Derived2 is public derivation from Derived, b is now protected member of Derived2
        c = 30;  //Not Allowed, Compiler Error
    }
};

int main()
{
    Derived obj;
    obj.a = 10;  //Not Allowed, Compiler Error
    obj.b = 20;  //Not Allowed, Compiler Error
    obj.c = 30;  //Not Allowed, Compiler Error
}

记住,同样的访问规则也适用于继承层次结构下的类和成员。

需要注意的要点:

-访问规范按类而不是按对象

注意,访问规范C++在每个类的基础上工作,而不是按每个对象。一个很好的例子是,在复制构造函数或复制分配运算符函数中,可以访问所传递对象的所有成员。

-派生类只能访问其自己的基类的成员

请考虑以下代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Myclass
{
    protected:
       int x;
};

class derived : public Myclass
{
    public:
        void f( Myclass& obj )
        {
            obj.x = 5;
        }
};

int main()
{
    return 0;
}

它给出一个编译错误:

prog.cpp:4: error: ‘int Myclass::x’ is protected

因为派生类只能访问它自己的基类的成员。注意,这里传递的对象obj与正在访问它的derived类函数没有任何关系,它是一个完全不同的对象,因此derived成员函数不能访问它的成员。

什么是friendfriend如何影响访问规范规则?

您可以将一个函数或类声明为另一个类的friend。这样做时,访问规范规则不适用于friended类/函数。类或函数可以访问该特定类的所有成员。

So do friends break Encapsulation?

不,他们没有,相反,他们增强了封装!

friend船用于表示两个实体之间有意的强耦合。如果两个实体之间存在特殊关系,即一个实体需要访问其他PrivateProtected成员,但您不希望每个人都使用Public访问说明符进行访问,则应使用friend船。


Scott Meyers在有效C++中的解释可能有助于理解何时使用它们——公共继承应该对IS-A关系进行建模,而私有继承应该用于"以"的形式实现——因此,您不必坚持超类的接口,而只是重用实现。