12

Какова разница между публичным, приватным и защищённым наследованием?

7

Вопрос: Какова разница между public, private и protected наследованием в C++?

Описание проблемы: Я изучаю C++ и пытаюсь разобраться в различных типах наследования, но не могу понять, как именно различаются public, private и protected наследования. Как они влияют на доступ к членам базового класса в производном классе и вне его? Можете ли вы объяснить различия с примерами кода?

5 ответ(ов)

12

Чтобы ответить на этот вопрос, сначала я хотел бы описать аксессоры членов класса своими словами. Если вы уже это знаете, можете пропустить раздел "дальше:".

Существуют три типа доступа, о которых я знаю: public, protected и private.

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

class Base {
    public:
        int publicMember;
    protected:
        int protectedMember;
    private:
        int privateMember;
};
  • Все, кто имеет доступ к классу Base, также знают о наличии publicMember.
  • Только дочерние классы (и их дочерние классы) знают о наличии protectedMember в Base.
  • Никто, кроме Base, не знает о privateMember.

Под "знает" я имею в виду "признает существование и, следовательно, может получить доступ".

дальше:

То же самое происходит с публичным, защищенным и приватным наследованием. Рассмотрим класс Base и класс Child, который наследует от Base.

  • Если наследование public, то все, кто знает о Base и Child, также знают о том, что Child наследуется от Base.
  • Если наследование protected, только Child и его дочерние классы знают о том, что они наследуют от Base.
  • Если наследование private, то никто, кроме Child, не знает о самом наследовании.
1

Ограничение видимости наследования сделает код неспособным увидеть, что какой-то класс наследует другой класс: не будут работать неявные преобразования от производного к базовому классу, а также static_cast от базового к производному классу.

Только члены/друзья класса могут видеть приватное наследование, а только члены/друзья и производные классы могут видеть защищенное наследование.

Публичное наследование

  1. Наследование типа IS-A. Кнопка является окном, и везде, где требуется окно, можно использовать и кнопку.

    class button : public window { };
    

Защищенное наследование

  1. Защищенное наследование, реализуемое через. Редко полезно. Используется в boost::compressed_pair для наследования от пустых классов и экономии памяти с помощью оптимизации пустых базовых классов (в приведенном ниже примере не используется шаблон для упрощения):

    struct empty_pair_impl : protected empty_class_1 
    { non_empty_class_2 second; };
    
    struct pair : private empty_pair_impl {
      non_empty_class_2 &second() {
        return this->second;
      }
    
      empty_class_1 &first() {
        return *this; // обратите внимание, что мы возвращаем *this!
      }
    };
    

Приватное наследование

  1. Реализация через. Использование базового класса предназначено только для реализации производного класса. Полезно с шаблонами и если важен размер (пустые шаблоны, которые содержат только функции, будут использовать оптимизацию пустых базовых классов). Часто решение с содержимым оказывается более эффективным. Размер строк критичен, так что это часто встречается здесь.

    template<typename StorageModel>
    struct string : private StorageModel {
    public:
      void realloc() {
        // использует унаследованную функцию
        StorageModel::realloc();
      }
    };
    

Публичный член

  1. Агрегация

    class pair {
    public:
      First first;
      Second second;
    };
    
  2. Инкапсуляторы

    class window {
    public:
        int getWidth() const;
    };
    

Защищенный член

  1. Обеспечение улучшенного доступа для производных классов

    class stack {
    protected:
      vector<element> c;
    };
    
    class window {
    protected:
      void registerClass(window_descriptor w);
    };
    

Приватный член

  1. Поддержание деталей реализации

    class window {
    private:
      int width;
    };
    

Обратите внимание, что приведение типов в стиле C позволяет намеренно использовать преобразование производного класса в защищенный или приватный базовый класс безопасным способом, а также преобразование в другом направлении. Это следует избегать любой ценой, так как может сделать код зависимым от деталей реализации — однако, если это необходимо, можно использовать такую технику.

0

Это связано с тем, как публичные члены базового класса доступны из производного класса.

  • public - члены публичного класса базового класса будут публичными (обычно это значение по умолчанию).
  • protected - члены публичного класса базового класса будут защищенными.
  • private - члены публичного класса базового класса будут приватными.

Как указывает litb, публичное наследование — это традиционное наследование, которое вы увидите в большинстве языков программирования. Оно моделирует отношение "Является" (IS-A). Частное наследование, которое, насколько мне известно, является особенностью C++, представляет собой отношение "Реализовано на основе" (IMPLEMENTED IN TERMS OF). То есть, вы хотите использовать публичный интерфейс в производном классе, но не хотите, чтобы пользователь производного класса имел доступ к этому интерфейсу. Многие считают, что в таком случае стоит использовать агрегацию базового класса, то есть вместо того, чтобы делать базовый класс приватным, лучше сделать его членом производного класса, чтобы повторно использовать функциональность базового класса.

0

В контексте наследования в объектно-ориентированном программировании, доступ к членам базового класса зависит от их уровня доступа. Вот как это выглядит:

  1. Private (Приватный):

    • Члены с модификатором доступа private недоступны в производном классе.
    • Их нельзя наследовать.
    • Поэтому, в результате, они остаются private для производного класса.
  2. Protected (Защищенный):

    • Члены с модификатором доступа protected доступны в производном классе и могут быть использованы с тем же уровнем доступа.
    • Они остаются protected в производном классе.
  3. Public (Публичный):

    • Члены с модификатором доступа public доступны для всех, включая производные классы.
    • В производном классе такие члены остаются public.

Итак, результат будет следующим:

Member in base class : Private   Protected   Public   

Тип наследования :             Объект наследован как:

Private            :   Inaccessible   Private     Private   
Protected          :   Inaccessible   Protected   Protected  
Public             :   Inaccessible   Protected   Public

Это означает, что:

  • Приватные члены базового класса недоступны в производном классе.
  • Защищенные члены доступны в производном классе и сохраняют свой уровень доступа.
  • Публичные члены также остаются доступными и публичными.
0

Наследование в C++: Публичное, Защищенное и Приватное

  1. Публичное наследование (Public Inheritance):

      1. Приватные члены базового класса недоступны в производном классе.
      1. Защищенные члены базового класса остаются защищёнными в производном классе.
      1. Публичные члены базового класса остаются публичными в производном классе.

    В результате, другие классы могут использовать публичные члены базового класса через объект производного класса.

  2. Защищенное наследование (Protected Inheritance):

      1. Приватные члены базового класса недоступны в производном классе.
      1. Защищенные члены базового класса остаются защищёнными в производном классе.
      1. Публичные члены базового класса также становятся защищёнными членами производного класса.

    В этом случае, другие классы не могут использовать публичные члены базового класса через объект производного класса, но они остаются доступны для подклассов производного класса.

  3. Приватное наследование (Private Inheritance):

      1. Приватные члены базового класса недоступны в производном классе.
      1. Защищенные и публичные члены базового класса становятся приватными членами производного класса.

    Таким образом, никакие члены базового класса не могут быть доступны другим классам через объект производного класса, так как они являются приватными в производном классе. Даже подклассы производного класса не могут получить к ним доступ.

Если у вас есть дополнительные вопросы по этому вопросу, не стесняйтесь задавать их!

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь