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

时间:2011-03-27 05:48:22

标签: c++ class private protected

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

2 个答案:

答案 0 :(得分:142)

什么是访问说明符?

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

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

受保护 - 声明为受保护的成员只能从类 BUT 外部访问,只能在从中派生的类中访问。

私人 - 只能在班级内访问这些成员。不允许外部访问。

源代码示例:

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。执行此操作时,访问规范规则不适用于friend ed类/函数。类或函数可以访问该特定类的所有成员。

  

那么friend打破封装吗?

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

friend发货用于表示两个实体之间的 故意强耦合
如果两个实体之间存在特殊关系,则需要访问其他privateprotected成员,但您不希望 所有人 使用public访问说明符进行访问时,您应该使用friend发货。

答案 1 :(得分:4)

Scott Meyers在Effective C ++中的解释可能有助于理解何时使用它们 - 公共继承应该建模是一种关系,而私有继承应该用于“is-implemented-in-terms-of” - 所以你不要不得不遵守超类的接口,你只需重用实现。