Полиморфизм и сокрытие данных: перекрывает или игнорирует базовый класс ограничения доступа производного класса? - PullRequest
3 голосов
/ 10 октября 2011

Пожалуйста, посмотрите на следующий список кодов:

#include <iostream>

using namespace std;

class Base {
public:
    virtual void Message() = 0;
};

class Intermediate : public Base {

};

class Final : public Intermediate {
    void Message() {
        cout << "Hello World!" << endl;
    }
};

int main() {
    Final final;
    /* Wont work (obviously):
    Final* finalPtr = &final;
    finalPtr->Message();
    */
    // Works:
    Intermediate* finalPtr = &final; // or Base* finalPtr = &final;
    finalPtr->Message();

    return 0;
}

Обратите внимание на следующее:

  1. В абстрактном Base классе чисто виртуальная функция message () является общедоступной
  2. Промежуточный класс (также абстрактный) наследуется от Базовый класс (Функция message () остается общедоступной виртуальной в Промежуточном ? ) * * тысяча двадцать-один
  3. Окончательный класс наследует от Промежуточный класс и функция message () является приватной (по умолчанию)
  4. В основном создается объект типа Final
  5. Промежуточный указатель на Final объект создан

Вопрос: Если вы запустите программу, строка finalPtr-> Message (); успешно вызовет реализацию Final message () , хотя ее private . Как это происходит? Базовый класс переопределяет или игнорирует ограничения доступа производного класса?

Вопрос по теме: Что касается (2.) выше, как правильно определить класс Intermediate ? Нужно ли повторно объявлять чисто виртуальную функцию message () из базового класса, учитывая, что класс Intermediate не предназначен для обеспечения реализации.

ПРИМЕЧАНИЕ: Код был протестирован с использованием компилятора Digital Mars (dmc) и Microsoft Visual Studio Compiler (cl) и отлично работает в обоих

Ответы [ 2 ]

4 голосов
/ 10 октября 2011

Как это происходит? Базовый класс переопределяет или игнорирует ограничения доступа производного класса?

При использовании Public Inheritance все открытые члены базового класса становятся открытыми членами производного класса. Так что Да Message() является публичной функцией в Intermediate.

Функция вызывается по указателю базового класса (Intermediate). Функция общедоступна в базовом классе. Динамическая диспетчеризация (т.е. фактический вызов функции класса Derived) происходит только во время выполнения, поэтому это работает.

Вышесказанное связано с тем, что во время выполнения спецификаторы доступа не имеют значения, правила спецификатора доступа разрешаются и действуют только во время компиляции.

Если вы вызываете функцию по указателю производного класса, то во время компиляции компилятор обнаруживает, что Message() объявлен private в Final и, следовательно, выдает ошибку.


При наследовании от класса Abstract производный класс ДОЛЖЕН предоставить определение для ALL виртуальных функций Pure базового класса, в противном случае это приведет также к классу Derived. будучи абстрактным классом.

Здесь Intermediate класс - это абстрактный класс, и если вам не нужно создавать объекты этого класса, он будет работать нормально. Обратите внимание, что вы можете создать указатель на абстрактный класс.

1 голос
/ 10 октября 2011

В C ++ виртуальные и спецификаторы доступа являются взаимоисключающими.Вот почему в C ++ доступ для виртуальных методов может быть ограничен, тогда как в C # или Java это невозможно.

Когда вы пытаетесь получить доступ к виртуальной функции через указатель базового класса, компилятор компилирует код, поскольку виртуальная функция базового класса является публичной.

В вашем закомментированном коде виртуальная функция с ограниченным доступом вызывается через указатель класса Final.Отсюда и ошибка компиляции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...