Наследование в C++: создание мощных классов с повторным использованием кода
Наследование в C++
В этом руководстве мы изучим наследование в C++ на примерах — от базового синтаксиса до protected-членов и режимов доступа.
Наследование — одна из ключевых особенностей объектно-ориентированного программирования в C++. Оно позволяет создавать новый класс (производный) на основе существующего (базового).
Производный класс наследует свойства базового класса и может иметь свои дополнительные особенности. Например:
class Animal {
// функция eat()
// функция sleep()
};
class Dog : public Animal {
// функция bark()
};
Здесь класс Dog наследуется от класса Animal. Поскольку Dog производен от Animal, члены Animal доступны в Dog.

Обратите внимание на ключевое слово 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 { /* код */ };
Различные способы наследования называются режимами доступа. Их влияние:
- public: Члены базового класса наследуются «как есть».
- private: Все члены базового класса становятся
privateв производном. - protected:
publicчлены базового становятсяprotectedв производном.
private члены базового класса всегда остаются private в производном.
Подробнее: руководство по public, private, protected наследованию.
Переопределение функций-членов при наследовании
Если базовый и производный классы имеют функции-члены с одинаковым именем и аргументами, то при вызове через объект производного класса выполняется версия производного класса. Функция производного класса переопределяет функцию базового.
Подробнее: переопределение функций в C++.
Рекомендуемое чтение: Множественное наследование в C++
Язык C
- Ключевое слово static в C#: статические переменные, методы и классы
- Вложенные классы в C#: определение, использование и наследование
- Освоение операторов C++: полное руководство с практическими примерами
- Классы и объекты в C++: практическое руководство по объектно-ориентированному программированию
- Публичное, защищённое и приватное наследование в C++: подробный разбор
- Шаблоны классов в C++: практическое руководство
- Наследование в Python: концепции, синтаксис и практические примеры
- Классы хранения в C++: область видимости, время жизни и использование
- Полиморфизм в C++: практическое руководство
- Абстракция данных в C++: разделение интерфейса и реализации