Урок №160. Сокрытие методов родительского класса

  Юрий  | 

  Обновл. 15 Сен 2021  | 

 19478

 ǀ   4 

Язык C++ предоставляет возможность изменить спецификатор доступа родительского члена в дочернем классе. Это делается с помощью «using-объявления». Например, рассмотрим следующий класс Parent:

Поскольку Parent::printValue() объявлен как protected, то он доступен только другим членам Parent и своим дочерним классам. Для других объектов доступ к нему закрыт.

Определим класс Child, который изменяет спецификатор доступа printValue() с protected на public:

Это означает, что следующий код выполнится без ошибок:

Здесь есть два примечания:

   Во-первых, вы можете изменить спецификаторы доступа только для тех членов родительского класса, к которым есть доступ у дочернего класса. Вы не сможете изменить спецификатор доступа члена родительского класса с private на protected или public, поскольку дочерний класс не имеет доступа к private-членам родительского класса.

   Во-вторых, начиная с C++11 использование «using-объявления» является предпочтительным способом изменения спецификаторов доступа. Однако вы также можете использовать «access-объявление». Это работает идентично «using-объявлению», только без ключевого слова using. Сейчас этот способ считается устаревшим, но, проглядывая более старый код, вы можете увидеть «access-объявления», поэтому об этом стоит знать.

Сокрытие родительских методов в дочернем классе

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

Например, вы можете сделать открытый член родительского класса закрытым:

Это позволяет инкапсулировать данные родительского класса в дочернем классе. В качестве альтернативы можно использовать наследование типа private, что приведет к тому, что все наследуемые public- и protected-члены класса Parent станут private в классе Child.

Вы также можете закрыть родительские методы в дочернем классе, используя ключевое слово delete:

Таким образом, компилятор будет жаловаться, если мы попытаемся вызвать метод getValue() через объект класса Child. Однако через объект родительского класса всё будет работать, так как мы «удалили» getValue() только в дочернем классе.


Оценить статью:

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (155 оценок, среднее: 4,92 из 5)
Загрузка...

Комментариев: 4

  1. Kris:

    По-моему, это не чистая инкапсуляция методов. Даже если мы напишем в классе Child так:

    Мы все равно сможем обратиться к этому методу так:

    Поэтому, это не чистая инкапсуляция. Хотя, вроде бы, если Parent позволяет обращаться к getValue(), то это значит, что нет смысла ругаться на "чистоту инкапсуляции", ибо изначально ее как таковой и не было. В общем, как-то так.

  2. Nikita:

    А через методы дочернего класса, удаленный метод родительского класса все ровно работает. Почему?

  3. kmish:

    Еще можно скрыть родительский метод его переопределением. Ну это так, до кучи:

    1. DarkMatter:

      Не то, чтобы мы его так скрываем, мы просто создаём новый объект с тем же именем, которое уже будет скрытым (будь то метод или переменная-член), объект же родителя будет доступен при явном указании области видимости Parent::Something, его мы вообще никак не затронули физически.

      В таком случае лучше всё же использовать модификаторы для наследуемого класса (private/protected) или тот же using/delete, тут намерения что-то скрыть будут яснее для читателя

Добавить комментарий

Ваш E-mail не будет опубликован. Обязательные поля помечены *