Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Industrial programming >> Язык C

Наследование в C++: создание мощных классов с повторным использованием кода

Наследование в C++

В этом руководстве мы изучим наследование в C++ на примерах — от базового синтаксиса до protected-членов и режимов доступа.

Наследование — одна из ключевых особенностей объектно-ориентированного программирования в C++. Оно позволяет создавать новый класс (производный) на основе существующего (базового).

Производный класс наследует свойства базового класса и может иметь свои дополнительные особенности. Например:

class Animal {
    // функция eat()
    // функция sleep()
};

class Dog : public Animal {
    // функция bark()
};

Здесь класс Dog наследуется от класса Animal. Поскольку Dog производен от Animal, члены Animal доступны в Dog.

Наследование в C++: создание мощных классов с повторным использованием кода

Обратите внимание на ключевое слово public при наследовании:

class Dog : public Animal {...};

Можно также использовать private и protected вместо public. Различия между ними разберём позже.


Отношение is-a (является)

Наследование представляет собой отношение is-a («является»). Оно используется только если такое отношение присутствует между двумя классами.

Примеры:


Пример 1: Простое наследование в C++

// C++ программа для демонстрации наследования
#include <iostream>
using namespace std;

// Базовый класс
class Animal {
public:
    void eat() {
        cout << "I can eat!" << endl;
    }
    void sleep() {
        cout << "I can sleep!" << endl;
    }
};

// Производный класс
class Dog : public Animal {
public:
    void bark() {
        cout << "I can bark! Woof woof!!" << endl;
    }
};

int main() {
    // Создание объекта класса Dog
    Dog dog1;
    
    // Вызов членов базового класса
    dog1.eat();
    dog1.sleep();
    
    // Вызов члена производного класса
    dog1.bark();
    return 0;
}

Вывод

I can eat!
I can sleep!
I can bark! Woof woof!!

Объект dog1 (производного класса Dog) может обращаться к членам базового класса Animal, потому что Dog унаследован от Animal.

// Вызов членов класса Animal
dog1.eat();
dog1.sleep();

Члены protected в C++

Модификатор доступа protected особенно важен в контексте наследования.

Как и private члены, protected недоступны снаружи класса. Однако они доступны производным классам и дружественным (friend) классам/функциям.

protected нужен, если мы хотим скрыть данные класса, но при этом позволить их наследовать производными классами.

Подробнее о protected см. в руководстве по модификаторам доступа C++.


Пример 2: Члены protected в C++

// C++ программа для демонстрации protected-членов
#include <iostream>
#include <string>
using namespace std;

// Базовый класс
class Animal {
private:
    string color;
protected:
    string type;
public:
    void eat() {
        cout << "I can eat!" << endl;
    }
    void sleep() {
        cout << "I can sleep!" << endl;
    }
    void setColor(string clr) {
        color = clr;
    }
    string getColor() {
        return color;
    }
};

// Производный класс
class Dog : public Animal {
public:
    void setType(string tp) {
        type = tp;
    }
    void displayInfo(string c) {
        cout << "I am a " << type << endl;
        cout << "My color is " << c << endl;
    }
    void bark() {
        cout << "I can bark! Woof woof!!" << endl;
    }
};

int main() {
    Dog dog1;
    
    // Члены базового класса
    dog1.eat();
    dog1.sleep();
    dog1.setColor("black");
    
    // Члены производного класса
    dog1.bark();
    dog1.setType("mammal");
    
    // Использование getColor() как аргумента
    dog1.displayInfo(dog1.getColor());
    return 0;
}

Вывод

I can eat!
I can sleep!
I can bark! Woof woof!!
I am a mammal
My color is black

Переменная type объявлена как protected, поэтому она доступна из производного класса Dog. Мы инициализируем её в Dog через setType().

С другой стороны, private переменная color недоступна в Dog:

class Dog : public Animal {
public:
    void setColor(string clr) {
        // Ошибка: член "Animal::color" недоступен
        color = clr;
    }
};

Также, поскольку protected скрывает данные, мы не можем обратиться к type напрямую из объекта Dog или Animal:

// Ошибка: член "Animal::type" недоступен
dog1.type = "mammal";

Режимы доступа при наследовании в C++

До сих пор мы использовали public для наследования. Но можно также использовать private и protected:

class Animal { /* код */ };
class Dog : private Animal { /* код */ };
class Cat : protected Animal { /* код */ };

Различные способы наследования называются режимами доступа. Их влияние:

  1. public: Члены базового класса наследуются «как есть».
  2. private: Все члены базового класса становятся private в производном.
  3. protected: public члены базового становятся protected в производном.

private члены базового класса всегда остаются private в производном.

Подробнее: руководство по public, private, protected наследованию.


Переопределение функций-членов при наследовании

Если базовый и производный классы имеют функции-члены с одинаковым именем и аргументами, то при вызове через объект производного класса выполняется версия производного класса. Функция производного класса переопределяет функцию базового.

Подробнее: переопределение функций в C++.


Рекомендуемое чтение: Множественное наследование в C++

Язык C

  1. Ключевое слово static в C#: статические переменные, методы и классы
  2. Вложенные классы в C#: определение, использование и наследование
  3. Освоение операторов C++: полное руководство с практическими примерами
  4. Классы и объекты в C++: практическое руководство по объектно-ориентированному программированию
  5. Публичное, защищённое и приватное наследование в C++: подробный разбор
  6. Шаблоны классов в C++: практическое руководство
  7. Наследование в Python: концепции, синтаксис и практические примеры
  8. Классы хранения в C++: область видимости, время жизни и использование
  9. Полиморфизм в C++: практическое руководство
  10. Абстракция данных в C++: разделение интерфейса и реализации