5.06. ООП
ООП
C++ полностью поддерживает ООП: инкапсуляция, наследование, полиморфизм, абстракция.
Объявление класса:
class Person {
private:
string name;
public:
Person(string n) : name(n) {}
void greet() const {
cout << "Hello, my name is " << name << endl;
}
};
Создание экземпляра:
Person p("Alice");
p.greet();
Наследование:
class Student : public Person {
public:
Student(string n) : Person(n) {}
};
Инкапсуляция:
Доступ к членам класса контролируется модификаторами:
- private
- protected
- public
Полиморфизм:
Поддерживается через виртуальные функции и переопределение:
class Animal {
public:
virtual void speak() { cout << "Animal sound" << endl; }
};
class Dog : public Animal {
public:
void speak() override { cout << "Woof!" << endl; }
};
Конструкторы / деструкторы:
class MyClass {
public:
MyClass() { cout << "Constructor" << endl; }
~MyClass() { cout << "Destructor" << endl; }
};
Перегрузка функций и операторов:
int add(int a, int b) { return a + b; }
double add(double a, double b) { return a + b; }
// Перегрузка оператора
class Point {
public:
int x, y;
Point operator+(const Point& other) {
return Point{x + other.x, y + other.y};
}
};
Управление памятью:
Ручное управление через new / delete
Поддержка умных указателей (unique_ptr, shared_ptr) начиная с C++11
unique_ptr<int> p(new int(5));
Шаблоны (Templates):
Поддерживают обобщённое программирование.
template<typename T>
T max(T a, T b) {
return (a > b) ? a : b;
}
cout << max(3, 5); // вызов с int
cout << max(3.5, 2.1); // вызов с double
STL (Standard Template Library):
Мощная библиотека, содержащая контейнеры, алгоритмы и итераторы.
Примеры:
vector<T>— динамический массивmap<K,V>— отображениеset<T>— множество
list<T> — двусвязный список
#include <vector>
vector<int> v = {1, 2, 3};
v.push_back(4);
Исключения:
Поддержка исключений через try / catch / throw.
try {
throw runtime_error("Error occurred!");
} catch (const exception& e) {
cerr << e.what() << endl;
}
Namespaces:
Организация кода в пространства имён.
namespace math {
int add(int a, int b) { return a + b; }
}
cout << math::add(2, 3);
Move семантика и Rvalue-ссылки (C++11+):
Увеличивает производительность при передаче/возврате больших объектов.
string createString() {
string temp = "Hello";
return temp; // move вместо копирования
}
Lambda-выражения (C++11+):
Анонимные функции.
auto sum = [](int a, int b) { return a + b; };
cout << sum(2, 3);
Smart Pointers (C++11+):
- unique_ptr — владение одним указателем
- shared_ptr — совместное владение
- weak_ptr — неувеличивает счетчик ссылок
C++ — один из самых мощных и гибких языков программирования. Он используется в разработке игр, системном ПО, высоконагруженных серверах, embedded-системах и многом другом. Хотя он сложнее по сравнению с языками вроде Python или Kotlin, он предоставляет максимальный контроль над производительностью и ресурсами.
Давайте рассмотрим его особенности
- Управление памятью.
В Java и C# есть сборщик мусора (GC) – не нужно думать о выделении и освобождении памяти. Объекты создаются в куче через new, но освобождаются автоматически.
В C++ нет сборщика мусора. Память управляется вручную. Объекты можно создавать локально (на стеке) и динамически (на куче):
Person p; // Локальный объект (стек)
Person* p = new Person(); // Объект на куче
delete p; // Нужно вручную удалить
В C++ программист отвечает за память, это сложно, но позволяет писать более быстрый и компактный код.
- Указатели и ссылки.
В Java нет указателей, только ссылки на объекты, которые нельзя арифметически изменять. В C++ есть указатели (*) и ссылки (&). Можно работать с адресами памяти, изменять значения напрямую.
int x = 10;
int* ptr = &x; // указатель на x
*ptr = 20; // меняем значение через указатель
int& ref = x; // ссылка на x
ref = 30; // тоже меняется x
C++ даёт прямой доступ к памяти, но и ответственность за ошибки тоже на программисте.
- Структуры и классы.
В Java только классы, struct отсутствует, все объекты – ссылочные типы.
В C++ есть class, и struct. Разница в уровне доступа по умолчанию, class - приватные члены по умолчанию, struct – публичные.
struct Point {
int x, y; // public по умолчанию
};
class Circle {
int radius; // private по умолчанию
public:
void setRadius(int r) { radius = r; }
};
В C++ struct и class – почти одно и то же, но struct часто используется для данных без логики.
- Перегрузка операторов.
В Java операторы нельзя перегружать. Исключение + для строк.
В C++ полная свобода – можно переопределять операторы.
Point operator+(const Point& a, const Point& b) {
return Point{a.x + b.x, a.y + b.y};
}
C++ поддерживает операторную перегрузку, что делает математические классы удобными.
- Шаблоны (Templates) и Generics.
В Java и C# Generics реализуются через типы-заполнители, но тип стирается во время выполнения.
List<int> list = new List<int>();
В C++ шаблоны – это метапрограммирование: шаблон компилируется для каждого типа отдельно.
template <typename T>
T max(T a, T b) {
return (a > b) ? a : b;
}
int i = max(3, 5); // инстанцирование для int
float f = max(3.1f, 5.6f); // инстанцирование для float
В C++ шаблоны – это часть компиляции, а не выполнения. Они мощнее, но сложнее в отладке.
- Конструкторы и деструкторы.
В Java есть конструкторы, есть финализатор finalize(), но его вызов не гарантирован.
public class MyClass {
public MyClass() { ... }
}
В C++ есть деструкторы, которые вызываются при выходе из области видимости:
class FileHandler {
public:
FileHandler(const char* name) { /* открываем файл */ }
~FileHandler() { /* закрываем файл */ }
};
{
FileHandler file("data.txt"); // при выходе из блока вызывается ~FileHandler()
}
Отличие в том, что в C++ есть RAII (Resource Acquisition Is Initialization) – управление ресурсами через деструкторы.
- Модификаторы доступа и уровни видимости.
В Java есть модификаторы: private, protected, public, package-private.
В C++ то же самое, но уровень доступа задаётся для групп членов класса:
class MyClass {
private:
int secret;
public:
void doSomething();
protected:
float internalData;
};
В C++ уровень доступа задаётся до члена класса, а не рядом с каждым.
- SLT (Standard Template Library).
C++ предоставляет мощную стандартную библиотеку, аналогичную Collections в Java или коллекциям в C#.
| Java | C# | C++ |
|---|---|---|
ArrayList<T> | List<T> | std::vector<T> |
HashMap<K,V> | Dictionary<K,V> | std::map<K,V> |
HashSet<T> | HashSet<T> | std::unordered_set<T> |
Queue<T> | Queue<T> | std::queue<T> |
SLT – шаблонная библиотека, очень гибка и эффективная, но требует понимания итераторов.
- Поддержка многопоточности.
| Язык | Поддержка потоков |
|---|---|
| Java | Thread, Runnable, ExecutorService |
| C# | Task, async/await, Thread |
| C++ | std::thread, std::mutex, std::future |
Пример:
#include <thread>
void threadFunc() {
std::cout << "Hello from thread";
}
int main() {
std::thread t(threadFunc);
t.join();
return 0;
}
В C++ нет встроенной поддержки async/await. Но можно использовать std::future, std::promise.
C++ это низкоуровневый, производительный и гибкий язык, который:
- даёт контроль над памятью и процессором;
- подходит для системного программирования, игр, embedded-систем;
- требует больше внимания к деталям, чем Java или C#.
Если мы знаем Java и C#, то работа с циклами, условиями, классами нам будет понятна, однако придётся научиться управлять памятью, понимать указатели, научиться работать с STL.