什么是访问说明符?我应该以私有、受保护还是公共继承?

Posted

技术标签:

【中文标题】什么是访问说明符?我应该以私有、受保护还是公共继承?【英文标题】:What are access specifiers? Should I inherit with private, protected or public? 【发布时间】:2011-07-23 18:44:08 【问题描述】:

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

【问题讨论】:

你想在哪里使用这个受保护的成员?您认为受保护意味着什么? 还有什么功能?你能给出一个给出错误的最小但完整的代码示例吗? @Sista - 发布您实际尝试做的代码。 @Mahesh - 感谢您的回复。我知道如何在 Als 的帮助下进行! @Sista:SO 是一个很棒的学习论坛,大多数人都愿意提供帮助,每个人都希望看到问题的清晰性、动机和学习意愿(尝试编写代码)或理解概念),而不是让人们为自己做这些事情。所以下次发帖时一定要记住要点。快乐学习! :) 【参考方案1】:

什么是访问说明符?

C++ 中的类/结构/联合有 3 个access specifiers。这些访问说明符定义了如何访问类的成员。当然,类的任何成员都可以在该类中访问(在同一类的任何成员函数内)。继续访问访问说明符的类型,它们是:

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

Protected - 声明为 Protected 的成员可以从类 BUT 外部访问,只能在从它派生的类中访问。

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


私有继承:

基类的所有Public成员变为派生类的Private成员& 基类的所有Protected 成员都成为派生类的Private 成员。

代码示例:

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


受保护的继承:

基类的所有Public成员都成为派生类的Protected成员& 基类的所有Protected 成员都成为派生类的Protected 成员。

代码示例:

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

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

考虑 following code example

class Myclass
 
    protected: 
       int x; 
; 

class derived : public Myclass

    public: 
        void f( Myclass& obj ) 
         
            obj.x = 5; 
         
;

int main()

    return 0;

它给出了一个编译错误:

prog.cpp:4: 错误:'int Myclass::x' 受保护

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


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

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

friends 也会破坏封装吗?

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

friendship 用于表示两个实体之间有意的强耦合。 如果两个实体之间存在特殊关系,即一个实体需要访问其他 privateprotected 成员,但您不希望 everyone 使用public 访问说明符,那么您应该使用 friendship。

【讨论】:

@Alf:谢谢Alf,我只是希望提问者通过答案学习。当我刚开始的时候,我必须自己学习,我知道这很难做到,只是努力做到最好。我确实将其标记为常见问题解答,但自从 Sbi 删除后,似乎答案不够好,或者可能不符合常见问题解答背后的想法。 非常感谢您的详细解释。我是 C++ 的新手,这确实帮助我理清了一些概念。很抱歉我不能早点回复。我不得不从图书馆回家,直到今天早上我才看到你的回复。我现在对访问说明符有了更清晰的了解。再次感谢。 很好的答案@Als,直接而简洁。 答案很好,但我相信对于一个常见问题解答它仍然缺少它所提供的:friend 的含义,与嵌套/成员类型的关系,更重要的是一个精确的定义受保护的含义以解决应该编译的常见误解:class base protected: int x; ; struct derived : base static void f( base& b ) b.x = 5; ; @DavidRodríguez-dribeas:当我回答这个问题时,它并不是一个常见问题解答条目,最终它是一个。我修改了答案以涵盖您指出的一些重要方面。确实它们很重要,谢谢提出。不过,我也觉得这个话题的范围和覆盖面很广,很难涵盖和触及所有方面。【参考方案2】:

Scott Meyers 在 Effective C++ 中的解释可能有助于理解何时使用它们:

公共继承应该模拟“is-a relationship”,而私有继承应该用于“is-implemented-in-terms-of”——所以你不必遵守超类的接口,你只是重用实现。

【讨论】:

以上是关于什么是访问说明符?我应该以私有、受保护还是公共继承?的主要内容,如果未能解决你的问题,请参考以下文章

公共/受保护/私有继承的问题

继承公共/受保护/私有构造函数

访问控制与继承

受保护继承的实际用途是啥?

子类真的继承私有成员变量吗?

如何禁止公共继承但允许私有(和受保护)继承