Что такое спецификаторы доступа? Должен ли я наследовать с частным, защищенным или публичным? - PullRequest
41 голосов
/ 27 марта 2011

Я запутался в значении модификаторов доступа в отношении наследования.В чем разница между наследованием ключевых слов private, protected и public?

Ответы [ 2 ]

142 голосов
/ 27 марта 2011

Что такое Спецификаторы доступа?

Есть 3 access specifiers для класса / структуры / Union в C ++. Эти спецификаторы доступа определяют, как получить доступ к членам класса. Конечно, любой член класса доступен в этом классе (внутри любой функции-члена этого же класса). Продвигаясь к типу спецификаторов доступа, они:

Public - Члены, объявленные как Public, доступны извне класса через объект класса.

Защищено - Члены, объявленные как Защищенные, доступны извне класса НО только в классе, производном от него.

Личное - Эти участники доступны только из класса. Доступ снаружи запрещен.

Пример исходного кода:

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 ++ работает для каждого класса, а не для каждого объекта.
Хорошим примером этого является то, что в конструкторе копирования или в функции оператора копирования можно получить доступ ко всем членам передаваемого объекта.

- Производный класс может иметь доступ только к членам своего базового класса

Рассмотрим следующий пример кода :

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 функция-член не может получить доступ к своим членам.


Что такое friend? Как friend влияет на правила спецификации доступа?

Вы можете объявить функцию или класс как friend другого класса. При этом правила спецификации доступа не применяются к классу / функции friend ed. Класс или функция могут получить доступ ко всем членам этого конкретного класса.

Так что же, friend s нарушает инкапсуляцию?

Нет, не делают, напротив, они улучшают инкапсуляцию!

friend судно используется для обозначения преднамеренной сильной связи между двумя объектами.
Если между двумя сущностями существуют особые отношения, так что одному нужен доступ к другим private или protected членам, но Вы не хотите, чтобы каждый имел доступ с помощью public указатель доступа, тогда вы должны использовать friend ship.

4 голосов
/ 18 июня 2012

Объяснение Скотта Мейерса из Effective C ++ может помочь понять, когда их использовать - публичное наследование должно моделировать отношения, в то время как частное наследование должно использоваться для "реализуется в терминах" - так что вы нене нужно придерживаться интерфейса суперкласса, вы просто повторно используете реализацию.

...