访问修饰符是什么?在继承中,我应该使用private、protected还是public?

50

对于继承中访问修饰符的含义我感到困惑,使用 privateprotectedpublic 关键字所涉及的继承有何区别?


9
你试图在哪里使用这个受保护的成员?你认为受保护的意思是什么? - James McNellis
还有哪些函数?你能提供一个最小但完整的代码示例,以便查看错误吗? - Eelke
1
@Sista - 发布你实际想要做的代码。 - Mahesh
@Mahesh - 感谢您的回复。我已经明白如何在Als的帮助下继续了! - Sista
@Sista:SO是一个非常好的学习论坛,大多数人都非常愿意帮助别人。但是我们希望看到的是问题清晰明了、有动力和学习意愿(尝试编写代码或理解概念),而不是让别人替自己完成任务。所以下次发帖时请记住这些要点。祝学习愉快! :) - Alok Save
2个回答

159

访问控制符是什么?

C++中有3种访问控制符,它们定义了类/结构体/联合体的成员如何被访问。当然,在类内部(在同一类的任何成员函数内部)可以访问该类的任何成员。接下来我们来看访问控制符的类型:

公共的(Public) - 声明为公共的成员,可以从类的对象外部进行访问。

保护的(Protected) - 声明为保护的成员,可以从派生类中进行访问 但不能在类外部使用。

私有的(Private) - 这些成员只能从类内访问,外部无法访问。

源代码示例:

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继承

下面是每个访问说明符的成员访问规则:

第一条最重要的规则是:类的private成员只能从同一个类的成员处访问。

公共继承:

基类的所有public成员成为派生类的public成员 &
基类的所有protected成员成为派生类的protected成员。

即成员的访问级别没有改变。我们之前讨论的访问规则然后应用于这些成员。

代码示例:

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

}

私有继承:

基类的所有公共成员变成派生类的私有成员,且
基类的所有保护成员变成派生类的私有成员。

一个代码示例:

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

}

受保护继承:

基类的所有公有成员变为派生类的受保护成员 &
基类的所有受保护成员也变成派生类的受保护成员。

一个代码示例:

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++的访问权限规定是以类为基础而不是对象为基础的。
一个很好的例子是,在复制构造函数或复制赋值运算符函数中,可以访问传递对象的所有成员。

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

考虑以下代码示例

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` 成员函数无法访问它的成员。


什么是“友元”?它如何影响访问规则?

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

那么,朋友会破坏封装吗?

不会,相反,它们增强了封装!

“友情”用于表示两个实体之间的有意义的紧密耦合关系。如果两个实体之间存在特殊关系,以至于一个需要访问另一个的`private`或`protected`成员,但您不希望每个人都可以使用`public`访问说明符访问,则应使用“友情”。


7
@Alf:谢谢你,我只是希望提问者能够从答案中学到东西。当我刚开始学习时,我必须自己摸索,我知道这很困难,所以我尽力而为。我已经将它标记为常见问题答案,但由于Sbi将其删除,似乎答案不够好,或者可能不符合常见问题答案的想法。 - Alok Save
4
非常感谢您提供详细的解释。我是C++的新手,这真的帮助我澄清了一些概念。很抱歉我没有能够早些回复。昨晚我不得不从图书馆回家,直到今天早上我才看到您的回复。现在我对访问说明符有了更清晰的理解。再次感谢。 - Sista
1
@Als,回答得很好,直接而简洁。 - codinguser
1
哇...这太棒了。我不想挑剔,但有人能编辑一下virtual如何影响继承吗?我是通过谷歌搜索到这里的。如果没有人在我学习之前编辑它,我会回到搜索结果并自己编辑的。 - Michael Hoffmann
1
这里有一个非常棒的答案。太棒了! - Prometheus
显示剩余3条评论

5

Scott Meyers在他的《Effective C++》一书中的解释可以帮助理解何时使用它们:

公有继承应该模拟“is-a关系”,而私有继承应该用于“基于实现”的情况-这样你就不必遵循超类的接口,只需重用实现即可。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接