Скрытие функционала базового класса

Последнее обновление: 14.03.2023

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

Скрытие функций

Производный класс может определить функцию с тем же именем, что и функция в базовом классе, с тем же или другим списком параметров. Для компилятора такая функция будет существовать независимо от базового класса. И подобное определение функции в производном классе не будет переопределением функции из базового класса.

#include <iostream>

class Person
{
public:
    Person(std::string name, unsigned age) : name(name), age(age)
    {}
    void print() const
    {
        std::cout << "Name: " << name << "\tAge: " << age << std::endl;
    }
private:
    std::string name;
    unsigned age;
};
class Employee: public Person
{
public:
    Employee(std::string name, unsigned age, std::string company): 
        Person(name, age), company(company)
    { }
    void print() const
    {
        std::cout << "Works in " << company << std::endl;
    }
private:
    std::string company;
};

int main()
{
    Employee tom{"Tom", 38, "Google"};
    tom.print(); // Works in Google
}

Здесь класс Person, который представляет человека, определяет функцию print(), которая выводит значение переменных name и age.

Класс Employee, который представляет сотрудника компании и является производным от класса Person, также определяет функцию print(), которая выводит значение переменной company.

В итоге объект Employee будет использовать реализацию функции print класса Employee, а не класса Person:

int main()
{
    Employee tom{"Tom", 38, "Google"};
    tom.print(); // Works in Google
}

Функция print в Employee скрывает функцию print класса Person. Однако иногда может потребоваться возможность вызвать реализацию функции, которая определена именно в базовом классе. В этом случае можно использовать оператор :::

базовый_класс::функция

Например:

#include <iostream>

class Person
{
public:
    Person(std::string name, unsigned age) : name(name), age(age)
    {}
    void print() const
    {
        std::cout << "Name: " << name << "\tAge: " << age << std::endl;
    }
private:
    std::string name;
    unsigned age;
};
class Employee: public Person
{
public:
    Employee(std::string name, unsigned age, std::string company): 
        Person(name, age), company(company)
    { }
    void print() const
    {
        Person::print();    // вызываем функцию print из базового класса
        std::cout << "Works in " << company << std::endl;
    }
private:
    std::string company;
};

int main()
{
    Employee tom{"Tom", 38, "Google"};
    tom.print();
}

Здесь вызов

Person::print();

представляет обращение к функции print базового класса Person. В итоге мы получим другой консольный вывод:

Name: Tom       Age: 38
Works in Google

Скрытие переменных

Производный класс может иметь переменные с тем же именем, что и базовый класс, Хотя такие ситуации могут привести к путанице, и, возможно, представляют нелучший вариант наименования переменных. Тем не менее мы можем так делать. Например:

#include <iostream>

class Integer
{
public:
    Integer(unsigned value): value(value)
    { }
    void printInteger() const
    {
        std::cout << value << std::endl;
    }
protected:
    unsigned value;
};
class Decimal: public Integer
{
public:
    Decimal(unsigned i_value, unsigned d_value): Integer(i_value), value(d_value)
    { }
    void printDecimal() const
    {
        std::cout << Integer::value << "." << value << std::endl;
    }
protected:
    unsigned value;
};

int main()
{
    Decimal decimal{12345, 3456};
    decimal.printInteger(); // 12345
    decimal.printDecimal(); // 12345.3456
}

Здесь класс Integer представляет целое число, значение которого хранится в переменной value. Этот класс наследуется классом Decimal, который представляет дробное число. Целая часть хранится в поле value класса Integer. А для хранения дробной части определена своя переменная value. Причем переменная value в Integer имеет спецификатор protected, поэтому теоретически мы могли бы обращаться к ней в классе Decimal. Однако поскольку в Decimal определена своя переменная value, то она скрывает переменную value и базового класса.

Чтобы все таки обратиться к переменной value из базового класса, надо использовать оператор :::

базовый_класс::переменная

например:

Integer::value

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

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850