С++ для интервью
37 subscribers
10 photos
Готовься к собеседованиям по C++ эффективно: реальные вопросы, типичные HR уловки, примеры кода и объяснения.
Каждый пост — один шаг ближе к офферу 💼
Download Telegram
💡 Правильный ответ: 2 и 3

🤓 Пояснения: Если fopen вернул nullptr, fclose(nullptr) — UB.
Кроме того, копирование File приведёт к двойному закрытию — класс должен быть не копируемым, а перемещаемым.
Please open Telegram to view this post
VIEW IN TELEGRAM
Что произойдёт при исключении в конструкторе?
Что делает такой шаблон RAII-защитника?
🧩 SOLID-принципы C++

Что такое SOLID и для чего он необходим?

1️⃣ S — Single Responsibility

Пояснение:
Класс делает узконаправленную задачу
Пример: Logger не должен писать в базу.

2️⃣ O — Open/Closed

Пояснение: Код открыт для расширения, но закрыт для модификации.
Пример: Использование виртуальных функций, шаблонов, полиморфизма.

3️⃣ L — Liskov Substitution

Пояснение:
Объекты подклассов можно использовать вместо базовых.
Пример: Если Derived ломает контракт Base, нарушен LSP.

4️⃣ I — Interface Segregation

Пояснение: Лучше несколько маленьких интерфейсов, чем один общий.

5️⃣ D — Dependency Inversion

Пояснение: Зависимости — от абстракций, а не от конкретных реализаций.
Пример: Использование родительского класса для создания экземпляра — unique_ptr<IService> вместо unique_ptr<MyService>.

⚙️ Пример использования SOLID

struct IShape {
virtual double area() const = 0;
virtual ~IShape() = default;
};

class Circle : public IShape {
double r_;
public:
explicit Circle(double r) :
r_(r) {}

double area() const override
{
return 3.14 * r_ * r_;
}
};


— SRP: Circle отвечает только за площадь круга.
— OCP: можно добавить Rectangle, не меняя IShape.
— LSP: любой IShape заменим на Circle.
— ISP: интерфейс компактный.
— DIP: зависимости через абстракции.

Подводя итог, SOLID — набор основных принципов, позволяющих писать читаемый, тестируемый и расширяемый C++ код.

#cpp_tips
🧬 CRTP (Curiously Recurring Template Pattern)

Как использовать шаблоны, а не виртуальность, чтобы дать базовому классу знать о потомке?


CRTP — это шаблон, где класс-наследник передаёт себя в качестве параметра шаблона базовому классу.

template <typename Derived>
class Base
{
public:
void interface()
{
static_cast<Derived*>
(this)->implementation();
}
};


А наследник выглядит так:

class Derived : public Base<Derived>
{
public:
void implementation()
{
std::cout << "Derived func\n";
}
};


⚙️ Как это работает

Когда ты вызываешь:

Derived d;
d.interface();


Базовый класс вызывает метод implementation() у конкретного типа Derived,
при этом без виртуальных функций — всё статически известно на этапе компиляции.

🚀 Где это полезно:

— Mixin — добавление поведения к классам без виртуальности.

— Policy-based design — подмена стратегий через шаблонные параметры.

— Статический полиморфизм — альтернатива virtual, но без runtime overhead.

— Ограничение интерфейса наследников — например, через enable_if и SFINAE.


🧠 Пример Mixin с CRTP

template <typename Derived>
class Printable
{
public:
void print() const
{
std::cout <<
static_cast<const Derived*>
(this)->toString();
}
};

class Point : public Printable<Point>
{
public:
Point(int x, int y) : x_(x), y_(y) {}
std::string toString() const
{
return std::to_string(x_) + ","
+ std::to_string(y_);
}
private:
int x_, y_;
};


Point p(2, 3);
p.print(); // 2,3


— Без virtual
— Без динамической памяти

— Гибко и эффективно

В итоге имеем:
CRTP — способ реализовать полиморфизм, заменив виртуальные вызовы статическим связыванием на этапе компиляции.

#cpp_tips
🧩 Тест 1 — Как работает вывод типов шаблона
Что выведет программа
Anonymous Quiz
0%
int
0%
double
100%
Ошибка компиляции
0%
auto
⚙️ Тест 2 — Передача по ссылке и вывод типов
Какой тип будет у T
Anonymous Quiz
0%
int
100%
const int
0%
int &
0%
const int &
🧩 Тест 3 — Как работает частичная специализация
⚙️ Type Traits: когда типы становятся логикой

Примеры Type Traits
template<typename T>
struct is_pointer
{
static constexpr bool value = false;
};

template<typename T>
struct is_pointer<T*>
{
static constexpr bool value = true;
};

assert(is_pointer<int*>::value);


🧠 Type Traits — шаблонные конструкции, которые предоставляют информацию о свойствах типов во время компиляции
Используются в std::enable_if, concepts, std::move.
Какой trait определяет, является ли тип числовым?
Anonymous Poll
0%
std::is_arithmetic
0%
std::is_integral
100%
std::is_numeric
🎯 Policy-based Design: шаблонная настройка поведения

Пример реализации:
template<typename ThreadPolicy, typename LogPolicy>
class Engine : private ThreadPolicy, private LogPolicy
{
public:
void run()
{
this->log("Starting...");
this->lock();
this->unlock();
}
};


✅ Вместо наследования от суперкласса составляем объект из политик, что позволяет легко менять поведение без лишнего кода.
Что проще изменить в Policy-based подходе?
Anonymous Poll
0%
Интерфейс базового класса
0%
Структуру иерархии
100%
Поведение
Expression Templates

Или магия ленивых выражений

Шаблоны выражений - это метод метапрограммирования шаблонов C++, который создает структуры, представляющие вычисления во время компиляции, где выражения вычисляются только по мере необходимости для создания эффективного кода для всего вычисления.

Таким образом, шаблоны выражений позволяют программистам обойти обычный порядок вычисления на языке C++ и добиться оптимизации, такой как объединение циклов.

Пример:
template<typename L, typename R>
struct Add
{
L const& l; R const& r;
auto eval() const
{
return l.eval() + r.eval();
}
};

struct Value
{
double v;
auto eval() const
{
return v;
}
};


🧠 Такие паттерны лежат в основе библиотек Eigen, Blitz++, Armadillo. Они предотвращают создание временных объектов — всё оптимизируется на этапе компиляции.