наследование — необходимо понимать утверждение «Доступность проверяется статически, а не динамически в C ++»

Я запутался относительно проверки спецификаторов доступа статически или динамически.
Говорят, что спецификаторы доступа не проверяются динамически. Что это значит ?

Этот пример был взят из разных сообщений на ТАК. Рассмотрим этот пример

Пример А:

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

class Intermediate : public Base
{
//Is Message method virtual here too ? is it private or public ?
};

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

Final final;

Теперь предположим, что я делаю что-то вроде этого

Final* finalPtr = &final;
finalPtr->Message();

Вышесказанное не сработает, и я понимаю, что в классе Final метод сообщения является закрытым. Это верно ? Если так, то почему это работает? метод в

  Intermediate* finalPtr = &final; // or Base* finalPtr = &final;
finalPtr->Message();

Является ли причиной того, что приведенный выше код работает, потому что указатель базового класса создается с помощью производного класса. Если так, почему работает вызов Message (). В посте о SO говорится, что, поскольку наследование является публичным, следовательно, оно будет наследоваться как публичная функция? с другой стороны, сама функция в классе имеет спецификатор приватного доступа (так как по умолчанию она приватна в классе). Я смущен здесь, и я был бы признателен, если бы кто-то мог прояснить это. Было бы правильно сказать, что если базовый класс создан с производным классом. Тогда спецификатор доступа метода базового класса имеет приоритет над спецификатором доступа производного класса?

Обновить :

Также я заметил, что если я изменю Intermediate а также Final код к следующему

class Intermediate : public Base
{
public: //Incase this public was absent then the following example wont work
void Message() {
cout << "Hello World! Intermediate" << endl;
}
};

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

и использовать его как таковой

 Intermediate* i = new Final();
i->Message();

Затем, чтобы получить вывод "Hello World! final" необходимо отметить метод интерфейса как общедоступный. Это почему ? Метод Message был унаследован как публичный. Почему я должен отметить это как общедоступное сейчас?

7

Решение

Утверждение в вашей цитате означает, что проверка доступа основана на статическом типе выражения, к которому вы применили . Оператор (или -> что эквивалентно * с .).

Если T это тип тогда для:

 T *t = something....;
t->foo();

проверка доступа для имени T::foo, даже если указатель фактически указывает на объект класса, производного от foo,

Еще один способ сказать, что проверка доступа должна выполняться во время компиляции. Не существует такого понятия, как «сбой доступности во время выполнения».


В вашем примере кода у вас есть:

Intermediate* finalPtr = something.....;
finalPtr->Message();

Имя ищется Intermediate::Message, Класс Intermediate имеет Message как public функция, так что эта проверка успешна.

Ваш комментарий предполагает, что, возможно, вы не уверены в доступности унаследованных функций. Есть три типа деривации (несколько запутанно, их также называют private, protected, public). public наследование является наиболее распространенным; это означает, что public члены базового класса также public члены производного класса.

поскольку Base::Message является публичным, и Intermediate публично получен из Base, затем Intermediate::Message также является публичным.

Чтобы было ясно, это имена которые имеют права доступа. Base::Message а также Intermediate::Message два разных имени, но они оба называют одну и ту же функцию.

В Final, он объявляет имя Message в его private раздел, это означает, что Final::Message это личное. Хотя наследство было публичным, новая декларация имени Final::Message тени, унаследованные от базы.


Ответить на «обновление». Когда код:

class Intermediate : public Base
{
public: //Incase this public was absent then the following example wont work
void Message() {
cout << "Hello World! Intermediate" << endl;
}
};

ты объявил Intermediate::Message как общедоступный. Поэтому вы можете вызывать функцию через указатель типа Intermediate *, Вот что значит «публика». Если вы сделаете это private тогда ты не сможешь это назвать.

Я не совсем понимаю, что вы подразумеваете под «Сообщение метода было унаследовано как общедоступное. Почему мне нужно пометить его как общедоступное». Когда ты написал void Message () внутри class Intermediate он объявляет новую функцию. Имя этой функции затеняет унаследованное имя.

8

Другие решения

Эта проверка выполняется только во время компиляции.

Вы сделали функцию Message () общедоступной в финале, чтобы ее можно было вызывать из финала.

Промежуточный класс не знает, как Message определяется в финальном классе.

4

Чтобы сделать ответ Мэтта Макнабба короче.
если вы не укажете доступ к функции, она будет закрытой. Like Final :: Сообщение

для производного класса возможно снизить доступность родительского класса. Это полезно в некоторых случаях (например, блокировка конструкторов по умолчанию / копирования и т. Д.)

1
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector