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

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

2 ответов


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

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

общественные - члены, объявленные как 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 члены производного класса &
Все!--8--> члены базового класса становятся 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 члены производного класса &
Все!--8--> члены базового класса становятся 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: error:’ int Myclass::x ' защищен

потому что производный класс может получить доступ только к членам своего собственный базовый класс. Обратите внимание, что объект obj быть переданным здесь никоим образом не связано с derived функция класса, в которой он доступен, это совершенно другой объект и, следовательно,derived функция-член не может получить доступ к своим членам.


что это friend? Как это friend повлиять на правила разграничения доступа?

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

так что friendперерыв инкапсуляции ы?

нет, наоборот они усиливают Инкапсуляция!

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


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