Глава 4. Объектно-ориентированное программирование в C++ #
4.2 Наследование в C++ #
1. Базовые принципы наследования #
Наследование - это механизм, позволяющий создавать новые классы на основе существующих, сохраняя и расширяя их функциональность.
// Базовый класс
class Animal {
protected:
std::string name;
public:
Animal(std::string n) : name(n) {}
void eat() {
std::cout << name << " ест." << std::endl;
}
virtual void makeSound() {
std::cout << "Какой-то звук" << std::endl;
}
};
// Производный класс
class Dog : public Animal {
public:
// Конструктор производного класса
Dog(std::string n) : Animal(n) {}
// Переопределение метода базового класса
void makeSound() override {
std::cout << name << " лает: Гав-гав!" << std::endl;
}
// Новый метод только для Dog
void fetch() {
std::cout << name << " приносит палку." << std::endl;
}
};
int main() {
Dog Rex("Рекс");
Rex.eat(); // Метод из базового класса
Rex.makeSound(); // Переопределенный метод
Rex.fetch(); // Метод производного класса
return 0;
}
2. Виды наследования #
C++ поддерживает три основных типа наследования:
Публичное наследование (public) #
class Base {
public:
int publicField;
protected:
int protectedField;
private:
int privateField;
};
// Публичное наследование сохраняет модификаторы доступа базового класса
class Derived : public Base {
void example() {
publicField; // Остается public
protectedField; // Остается protected
// privateField; // Недоступно
}
};
Защищенное наследование (protected) #
class Derived : protected Base {
void example() {
publicField; // Теперь protected
protectedField; // Остается protected
// privateField; // Недоступно
}
};
Приватное наследование (private) #
class Derived : private Base {
void example() {
publicField; // Теперь private
protectedField; // Теперь private
// privateField; // Недоступно
}
};
3. Множественное наследование #
C++ позволяет наследоваться от нескольких базовых классов:
class Engine {
public:
void start() {
std::cout << "Двигатель запущен" << std::endl;
}
};
class Wheel {
public:
void rotate() {
std::cout << "Колеса вращаются" << std::endl;
}
};
// Множественное наследование
class Car : public Engine, public Wheel {
public:
void drive() {
start(); // Метод из Engine
rotate(); // Метод из Wheel
std::cout << "Машина едет" << std::endl;
}
};
int main() {
Car myCar;
myCar.drive();
return 0;
}
4. Виртуальное наследование #
Решает проблему “ромбовидного наследования”:
class Animal {
protected:
std::string name;
public:
Animal(std::string n) : name(n) {}
};
// Виртуальное наследование
class Mammal : virtual public Animal {
public:
Mammal(std::string n) : Animal(n) {}
void breathe() {
std::cout << name << " дышит" << std::endl;
}
};
class Flyable : virtual public Animal {
public:
Flyable(std::string n) : Animal(n) {}
void fly() {
std::cout << name << " летит" << std::endl;
}
};
// Разрешаем конфликт инициализации базового класса
class Bat : public Mammal, public Flyable {
public:
Bat(std::string n) : Animal(n), Mammal(n), Flyable(n) {}
};
int main() {
Bat batman("Летучая мышь");
batman.breathe(); // Метод из Mammal
batman.fly(); // Метод из Flyable
return 0;
}
5. Ключевое слово override #
Ключевое слово override
помогает предотвратить ошибки при переопределении виртуальных методов:
class Shape {
public:
// Виртуальный метод в базовом классе
virtual double calculateArea() const {
return 0.0;
}
virtual ~Shape() {} // Виртуальный деструктор
};
class Circle : public Shape {
private:
double radius;
public:
Circle(double r) : radius(r) {}
// Корректное переопределение с использованием override
double calculateArea() const override {
return 3.14159 * radius * radius;
}
};
class Rectangle : public Shape {
private:
double width, height;
public:
Rectangle(double w, double h) : width(w), height(h) {}
// Еще одно переопределение
double calculateArea() const override {
return width * height;
}
};
// Демонстрация полиморфизма
void printArea(const Shape& shape) {
std::cout << "Площадь: " << shape.calculateArea() << std::endl;
}
int main() {
Circle circle(5.0);
Rectangle rect(4.0, 6.0);
printArea(circle); // Полиморфный вызов
printArea(rect); // Полиморфный вызов
return 0;
}
Заключение #
Наследование в C++ - мощный механизм объектно-ориентированного программирования, который позволяет:
- Создавать иерархии классов
- Переиспользовать код
- Реализовывать полиморфное поведение
- Моделировать сложные взаимосвязи между объектами
Ключевые моменты:
- Различные виды наследования
- Множественное наследование
- Виртуальное наследование
- Использование
override
для безопасного переопределения методов