ilyachalov (ilyachalov) wrote,
ilyachalov
ilyachalov

Categories:

Сокрытие имён при наследовании

Еще одни грабли, описание которых стоило бы включить в главу 9 «Наследование» учебника Лафоре. Ученик с размаху наступает на них в упражнении 7 к этой главе, не понимая, в чём дело.

Задание к упражнению 7 главы 9. Даны два класса, которые нельзя изменять. Вот сокращенный код этих классов (это нерабочий вариант, в целях упрощения оставлены только методы с пустым телом; то же касается и других фрагментов кода в этом посте):
// базовый класс, реализующий счетчик, с одним методом
class Counter
{
public:
    Counter operator++ () // метод увеличения счетчика на 1 (префиксный инкремент)
    { }
};

// производный класс, добавляющий к счетчику еще один метод
class CountDn : public Counter
{
public:
    CountDn operator-- () // метод уменьшения счетчика на 1 (префиксный декремент)
    { }
};
Требуется добавить к счетчику методы постфиксного инкремента и постфиксного декремента.

Решение. Так как заданные классы нельзя изменять, создадим новый класс с помощью наследования и добавим в него требуемые методы:
class Counter2 : public CountDn
{
public:
    Counter2 operator++ (int) // постфиксный инкремент
    { }
    Counter2 operator-- (int) // постфиксный декремент
    { }
};
Напишем программу для проверки работы нового класса:
int main()
{
    Counter2 c1;
    
    ++c1; // ошибка
    --c1; // ошибка
    c1++; // работает
    c1--; // работает
    
    return 0;
}
Компилятор «не видит» методы из двух родительских классов. Почему же не работает наследование?

Про области видимости имён (идентификаторов) в учебнике ранее немного рассказывалось в разных главах. Также рассказывалось и о перегрузке функций (методов классов), этому посвящена глава 8 учебника.

В главе 9 учебника сказано, что при наличии в базовом и производном классах методов с одинаковыми именами при вызове такого метода от объекта производного класса компилятор сначала ищет метод в производном классе и, если не находит, тогда ищет метод в базовом классе. Получается, что метод производного класса «закрывает видимость» на метод с таким же именем в базовом классе.

А вот про то, что то же самое работает даже при разном количестве параметров (или разном типе параметров) у методов с одинаковым именем из базового и производного классов, в учебнике не сказано и дойти до этого самому, без подсказки, очень непросто.

В данном упражнении два новых метода для постфиксного инкремента и постфиксного декремента «закрывают видимость» на методы родительских классов из-за того, что их имена совпадают.

Чтобы в данном случае методы родительских классов «стали видны» в нашем новом классе, можно объявить их имена с помощью ключевого слова using:
https://docs.microsoft.com/ru-ru/cpp/cpp/using-declaration

Например:
class Counter2 : public CountDn
{
public:
    using CountDn::operator++;
    using CountDn::operator--;
    Counter2 operator++ (int) // постфиксный инкремент
    { }
    Counter2 operator-- (int) // постфиксный декремент
    { }
};

Обсуждение на Киберфоруме (август 2014 г.):
http://www.cyberforum.ru/cpp-beginners/thread1240110.html
Tags: Образование, Программирование
Subscribe

  • Marcus Nimbler закрыл свой канал на YouTube

    Любопытный персонаж из Германии по имени Marcus Nimbler вел свой канал на «YouTube» с 25 февраля 2016 г. За это время у него накопилось 131 тыс.…

  • Сбыча мелких мечт

    В качестве эпиграфа: Но со временем я заметил, что для этого мира такое положение дел вполне естественно в любой области. Поначалу всегда есть две…

  • От любви к любви, Никольский

    Сейчас делал приседания и слушал наше местное радио. Кстати, интересная тема для зожников: делать каждый день по 100 приседаний. Посоветовали на…

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your IP address will be recorded 

  • 0 comments