Горячее
Лучшее
Свежее
Подписки
Сообщества
Блоги
Эксперты
Войти
Забыли пароль?
или продолжите с
Создать аккаунт
Я хочу получать рассылки с лучшими постами за неделю
или
Восстановление пароля
Восстановление пароля
Получить код в Telegram
Войти с Яндекс ID Войти через VK ID
Создавая аккаунт, я соглашаюсь с правилами Пикабу и даю согласие на обработку персональных данных.
ПромокодыРаботаКурсыРекламаИгрыПополнение Steam
Пикабу Игры +1000 бесплатных онлайн игр
Поднимайтесь как можно выше по дереву, собирайте цветы и дарите их близким.
Вас ждут уникальные награды и 22 выгодных промокода!

Пикаджамп

Аркады, Казуальные, На ловкость

Играть

Топ прошлой недели

  • AlexKud AlexKud 38 постов
  • SergeyKorsun SergeyKorsun 12 постов
  • SupportHuaport SupportHuaport 5 постов
Посмотреть весь топ

Лучшие посты недели

Рассылка Пикабу: отправляем самые рейтинговые материалы за 7 дней 🔥

Нажимая кнопку «Подписаться на рассылку», я соглашаюсь с Правилами Пикабу и даю согласие на обработку персональных данных.

Спасибо, что подписались!
Пожалуйста, проверьте почту 😊

Помощь Кодекс Пикабу Команда Пикабу Моб. приложение
Правила соцсети О рекомендациях О компании
Промокоды Биг Гик Промокоды Lamoda Промокоды МВидео Промокоды Яндекс Директ Промокоды Отелло Промокоды Aroma Butik Промокоды Яндекс Путешествия Постила Футбол сегодня

IT + Windows

С этим тегом используют

Программирование IT юмор Программист Юмор Работа Картинка с текстом Разработка Компьютер Компьютерная помощь Linux Microsoft Windows 10 Программа Все
657 постов сначала свежее
Fishrish
Fishrish
4 месяца назад
Лига программистов

Процессорный Шик: Когда Люди Играют Программистов⁠⁠

Музыка Программирование Программист IT юмор Python IT Windows Программа Видео Вертикальное видео Короткие видео
2
Fishrish
Fishrish
4 месяца назад
Лига программистов

Выбираем самого кринжового Айтишника. Как вам претендент?⁠⁠

Музыка Программирование Программист IT юмор Python IT Windows Программа Видео Вертикальное видео Короткие видео
3
Fishrish
Fishrish
4 месяца назад
Лига программистов

Новый тренд. Люди снимают кринжвидео изображая программистов под песню Ай Ти⁠⁠

Музыка Программирование Программист IT юмор Python IT Windows Программа Видео Вертикальное видео Короткие видео
1
59
DmitriitheFals
4 месяца назад
Лига Сисадминов
Серия Кудахтеры

Хабр пробивает донья или будьте осторожны в копроблогах - 03⁠⁠

Для ЛЛ: Мало кто знает, например, что у слова "дно" есть форма множественного числа - и это не "днища", а "донья". Про дичь и чушь в копроблогах Хабра.

На этот раз отличился копроблог RUVDS со статьей «Почему мы перешли на RAID 10».

Сначала вспомним базу.

RAID 0 - Striped Disk Array without Fault Tolerance.
Плюсы: пишем на все диски, читаем со всех дисков.
Write penalty – отсутствует.
Минусы: потеряли диск – потеряли данные.
Минимальное число дисков – 2.

RAID 1 – Mirror
Плюсы: пишем на все диски одинаковые данные, читаем со всех дисков.
потеряли диск – ну и ладно, считали все что было с оставшегося.
Write penalty – х2. То есть, чтобы записать 1 бит, надо выполнить и дождаться выполнения двух операций – на, условно, первый и второй диски, то есть на запись Mirror будет в два раза медленнее.
Минусы: полезная емкость - пополам (/2) для two-way mirror, бывает и 3-way
Минимальное число дисков – 2.

RAID 5 – одинарная четность.
Плюсы: пишем на все диски данные, и на один диск – итоги XOR. При выходе из строя любого диска – заменяем диск, применяем математику, восстанавливаем данные.
Write penalty (точнее, rewrite penalty) – 4, 4 операции: считать данные, считать четность, записать новые данные, записать новую четность.
Минусы: при выходе из строя еще одного диска – теряем данные.
Полезная емкость – N-1
Минимальное число дисков – 3 (данные, данные, четность)

RAID 6 – двойная четность.
Плюсы: пишем на все диски данные, и на два  диск – на один xor, на другой другую математику. При выходе из строя любого диска – заменяем диск, применяем математику, восстанавливаем данные.
Точно переживет выход из строя еще одного диска.
Минусы: Write penalty (точнее, rewrite penalty) – 6, 4 операции: считать данные, считать две четности, записать новые данные, записать две новые четности.
Полезная емкость – N-2
Минимальное число дисков – 4 (данные, данные, четность, четность)

RAID 10 – собираем два Raid 1, из них собираем Raid 0.
RAID DP, Raid triple parity – тройная четность плюс немного математической магии.

Немного магии.
Все производители RAID, как совсем железных, так и программных, используют разные фокусы для ускорения работы. Тут и буфер чтения и записи на raid, и mirror accelerated parity (MS), и SSD буфер на запись, и Write Anywhere File Layout (WAFL) – когда данные не перезаписываются, а пишутся в новые адреса, много тут всякой магии.

И немного современности.
Современные all-flash СХД могут вообще не использовать Raid 10. Те же Huawei Oceanstor Dorado используют Raid-5, RAID 6, RAID-TP (см. OceanStor Dorado 6.0.0 Basic Storage Service Configuration Guide)
Плюсы очевидны, емкость не пополам, а -2, -3, что легко компенсируется дедупликацией и сжатием. Скорость отличная за счет внутренних буферов (на батарейке) по 512 мб и больше.

Современные гиперконвергентные системы и вариации на тему Redundant Array of Inexpensive Servers (RAIS) or Redundant Array of Independent Nodes (RAIN) вообще не оперируют терминами raid, вместо этого используя термины Redundancy Factor (RF) и failure to tolerate (FTT) – то есть, число единиц хранения, которые могут выйти из строя. Про это можно почитать
Design and Operation Considerations When Using vSAN Fault Domains
Fault tolerance and storage efficiency on Azure Stack HCI and Windows Server clusters

Теперь, вспомнив базу, пойдем к статье - Почему мы перешли на RAID 10, и с первой строки
Недавно у нас развалился RAID 5.

Вопрос в чем. Идет 2025 год. Калькуляторы надежности рейдов в зависимости от числа неустранимых ошибок и наработки на отказ давно написаны, хотя там можно и руками посчитать. С 2010х существует эмпирическое правило – из дисков выше 1 Тб строить только R6. Откуда у них взялся R5, на каких дисках и на каком устройстве вы это собрали и зачем?

Один из пользователей, чьи данные там были, очень живо интересовался тем, что за конфигурация у нас была. Вплоть до моделей дисков, дат их производства и серийных номеров. Он, вероятно, считал, что там стоит какое-то старьё

Он мог задать всего один вопрос. R5 ? Тогда мы не идем к вам. Так то серьезные дяди выкладывают статистики наработки разных моделей и партий дисков -  вот тут, Backblaze Drive Stats for Q1 2024.

Потом очень искренне смеялся над фразой, что ни одна схема резервирования RAID не даёт стопроцентной гарантии сохранности данных.

Дает 99.9999 и еще сколько то девяток – скажем, метрокластер в RAID-TP. Вполне достаточно.

Раньше всё хранилось в RAID 5 (в абсолютном большинстве случаев)

В RUVDS – ни ногой, что еще сказать. Плюс, а что поверх? Автор пишет про диски на отдельном сервере, значит у них поверх намазано? А что? Что из SDS требует именно RAID ? Да, вроде бы, ничего, и более того, всему что я видел из RAIN – локальные raid прямо противопоказаны.

В большинстве случаев это рабочая ситуация.

В современном мире с текущей надежностью механических дисков это не рабочая ситуация. Похоже, в RUVDS не смогли даже в онлайн калькулятор надежности.
О чем я и пишу уже скоро год – идет медленное, незаметное, подгнивание качества ИТ кадров. Все было хорошо, а потом у них R5.

В RAID 10 — резервирование 2N: это два RAID 1,

Это не так. R10 не защитит от выхода из строя второго диска из пары, поэтому там надежность не 2N.

Фактически переход на RAID 10 означает плюс два или плюс три диска в каждый сервер. Это дорого: диски, конечно, — расходники, но при этом недешёвые.

Заявление на построение отказоустойчивости на уровне отдельного диска для хостинга означает отсутствие любой системы RAIN – то есть, при отказе не диска, а контроллера, точно получим недоступность, и возможно и потерю данных.

Это NVMe-RAID?
Нет. У нас везде — SSD: они хорошо соединяются в массивы.

NVME это интерфейс. То есть выбор интерфейса стоит между SAS, SATA и NVME.
SSD – стандарт диска, причем с уходом Optane – других и нет, выбор идет между QLC SSD vs. SLC vs. MLC vs. TLC.
Поэтому формулировка NVME RAID попросту бессмысленна,  да и NVME SSD отлично собираются в RAID , хотя и с определенной потерей производительности, но я про это раньше писал.
Только это не нужно, точнее бессмысленно, если серверов хотя бы три и можно собрать RAIN. Лучше, конечно, 6 серверов. 8-10 в самый раз.

Кластер — это другой хороший отказоустойчивый подход. Но там уже сам кластер становится точкой отказа, и практика показывает, что не такой уж и редкой.

Почему сразу кластер? Можно хранить на внешней СХД. RAIN, нормальный , теплый и проприетарный, тоже не взрывается, кроме как от кривых рук.

Вместо заключения.

Всего на хабре 400-500 активно голосующих участников, и число голосующих который год падает. Статья набрала сотню плюсов, а точнее +78 и -2. То есть 78 человек из 400 считают статью с кучей ошибок – вполне нормальной. Ну что тут сказать. Допустим 10-20 голосов это чистая накрутка, и остается 50\500, 10% людей, которых к системам хранения пускать нельзя.
Silent Data Corruption , она же bit rot – вот и она, только в кадрах - люди принципиально не понимают, что тут не так

Показать полностью
[моё] Опыт Windows IT Текст Длиннопост
31
301
user10283230
4 месяца назад
Программы и Браузеры

Как я создал современную альтернативу Lightshot для Windows 10/11⁠⁠

Я люблю Lightshot, но, к сожалению, его уже давно не обновляют, поэтому я решил сделать свою скриншотилку — с обновлённым дизайном, но с похожей логикой интерфейса.

Идея появилась ещё два года назад, и я думал, что это будет очень просто: возьму нативную технологию, стандартный дизайн Windows, найму фрилансера, и он быстренько запилит приложение в стиле Windows 11. Ведь это всего пара кнопок, да и языки программирования должны были давно уйти вперёд. Мне даже сделали первую версию за 40к. Вот только выглядела она совсем не в стиле Windows 11.

Как я создал современную альтернативу Lightshot для Windows 10/11 Приложение, Windows, Программа, Программирование, Разработка, IT, Windows 10, Windows 11, Indiedev, Стартап

После долгих попыток разобраться, как же так вышло, я пришёл к выводу, что на рынке очень мало разработчиков (и дорогих, и дешёвых), которые имеют опыт написания приложений на нативной технологии под Windows (а именно WinUI). Сейчас в моде кроссплатформенные решения, например, Electron. Но я твёрдо решил, что всё-таки завершу свой проект именно на нативной технологии. Всё-таки там всего пара кнопок! :)

Спустя 135 часов разработки и набивания шишек на WinUI 3 я пришёл к выводу, что Windows 11 хоть и красивый, но кодить под него достаточно сложно. Под капотом используется очень много прямых обращений к WinAPI (работа напрямую с ядром Windows), разработка под него ещё сырая, даже ChatGPT не всегда справляется. Но всё же мне удалось завершить проект, и теперь я ежедневно сам пользуюсь своей скриншотилкой и кайфую!

Более того я доработал многие функции по сравнению с лайтшотом: сделал сглаженный карандаш, добавил стрелки разного дизайна, добавил опциональный фон тексту, добавил возможность редактировать и перемещать текст, делать ресайз после выбора области, добавил блюр. В общем это всё лирика.

Всем кто любит лайтшот, зацените мою скришотилку!

Как я создал современную альтернативу Lightshot для Windows 10/11 Приложение, Windows, Программа, Программирование, Разработка, IT, Windows 10, Windows 11, Indiedev, Стартап

Скачать её можно здесь

Пока я не делал .exe, для этого надо было делать сайт и разбираться с установщиком. Если много кому будет нужна будет версия не из стора, то сделаю

Буду рад любой обратной связи и советам

UPD:

Скриншотилка называется Sleekshot

Показать полностью 2
[моё] Приложение Windows Программа Программирование Разработка IT Windows 10 Windows 11 Indiedev Стартап
183
5
mcnikirikitiki
4 месяца назад
Лига программистов

Основы программирования на C++: Наследование и полиморфизм⁠⁠

Прежде чем читать мою статью - реши для себя, зачем ты это делаешь. Даже если ты просто нормальный человек, лишним не будет.

Если вы настоящий профессионал программирования, то зачем вы тут сидите и читайте статью на пикабу? Если вы ради интереса зашли почитать, то претензий ноль, но если вы просто захотели задушить нового пользователя Пикабу минусами, то немедленно покиньте статью, вам однозначно интересно не будет.

Здравствуйте, мои маленькие любители программирования!

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

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


Пример наследования

class A {

private:

int x;

public:

void Func1();

void Func2();

};

class B : public A {

private:

int y;

public:

void Func2(); // Переопределение функции

void Func3();

};

Основные моменты:

  • Класс B включает в себя подобъект класса A.

  • Методы и поля класса A доступны в B, за исключением приватных полей.

  • Приватное поле x из A хранится внутри объекта типа B, но недоступно напрямую.

Использование:

int main() {

B b;

b.Func1(); // Унаследовано от A

b.Func2(); // Переопределено в B

b.A::Func2(); // Версия из A

b.Func3(); // Определено в B

}


Приведение типов

Объект производного класса может быть приведён к типу базового класса . Это позволяет использовать объекты производного класса там, где ожидается объект базового класса.

void DoSomething(const A&);

int main() {

B b;

DoSomething(b); // OK

}


Жизненный цикл объектов

При создании объекта производного класса сначала вызывается конструктор базового класса, затем конструктор производного. Деструкторы вызываются в обратном порядке.

class InheritedLogger : public Logger {

public:

InheritedLogger() { std::cout << "InheritedLogger()\n"; }

~InheritedLogger() { std::cout << "~InheritedLogger()\n"; }

};

int main() {

InheritedLogger x;

}

Вывод программы:

Logger(): 1

InheritedLogger()

~InheritedLogger()

~Logger(): 1


Наследование vs Композиция

Наследование (is-a):

  • Класс-наследник является частным случаем базового класса.

  • Пример: Car является Vehicle.

Композиция (has-a):

  • Класс содержит объект другого класса как поле.

  • Пример: Car имеет Engine.

Пример композиции:

class C {

private:

A a; // Композиция

int y;

public:

void Func1() { a.Func1(); } // Обёртка

void Func2();

void Func3();

const A& GetA() const { return a; }

};


Полиморфизм

Полиморфизм позволяет переопределять поведение функций базового класса в производных классах. Для этого используются виртуальные функции .

Пример:

class Animal {

public:

virtual std::string Voice() const { return "Generic voice"; }

};

class Cat : public Animal {

public:

std::string Voice() const override { return "Meow!"; }

};

class Dog : public Animal {

public:

std::string Voice() const override { return "Woof!"; }

};

Виртуальные функции:

  • Позволяют выбирать реализацию во время выполнения (позднее связывание ).

  • Если функция объявлена как чисто виртуальная , класс становится абстрактным .

class Animal {

public:

virtual std::string Voice() const = 0; // Чисто виртуальная функция

};

  • Создать объект абстрактного класса нельзя.

  • Производные классы должны реализовать все чисто виртуальные функции.


Полиморфизм и контейнеры

Для хранения объектов разных типов в контейнере используются указатели. Однако важно учитывать управление памятью.

Пример использования указателей:

std::vector<Animal*> zoo;

zoo.push_back(new Cat("Tom"));

zoo.push_back(new Dog("Buffa"));

for (Animal* animal : zoo) {

Process(*animal); // Полиморфное поведение

delete animal; // Освобождение памяти

}

Важно:

  • Для корректного удаления объектов деструктор базового класса должен быть виртуальным .

class Animal {

public:

virtual ~Animal() {}

};


Умные указатели

Для безопасного управления памятью лучше использовать умные указатели , такие как std::unique_ptr или std::shared_ptr.

Пример с std::unique_ptr:

std::vector<std::unique_ptr<Animal>> zoo;

zoo.push_back(std::make_unique<Cat>("Tom"));

zoo.push_back(std::make_unique<Dog>("Buffa"));

for (const auto& animal : zoo) {

Process(*animal); // Полиморфное поведение

}

  • Умные указатели автоматически освобождают память при выходе из области видимости.


Итог

  1. Наследование позволяет создавать иерархии классов и переиспользовать код.

  2. Виртуальные функции обеспечивают полиморфное поведение.

  3. Для работы с полиморфными объектами в контейнерах используйте указатели или умные указатели .

  4. Абстрактные классы помогают определить общий интерфейс для производных классов.

  5. Композиция предпочтительна, когда отношение между классами выражается через "имеет", а не "является".

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

Показать полностью
[моё] C++ IT Программирование Windows Длиннопост
15
2
mcnikirikitiki
4 месяца назад
Лига программистов

Основы программирования на C++: Жизненный цикл объекта⁠⁠

Прежде чем читать мою статью - реши для себя, зачем ты это делаешь. Даже если ты просто нормальный человек, лишним не будет.

Если вы настоящий профессионал программирования, то зачем вы тут сидите и читайте статью на пикабу? Если вы ради интереса зашли почитать, то претензий ноль, но если вы просто захотели задушить нового пользователя Пикабу минусами, то немедленно покиньте статью, вам однозначно интересно не будет.

Здравствуйте, мои маленькие любители программирования!

Жизненный цикл объекта в C++ управляется конструкторами, деструкторами и операторами присваивания. Рассмотрим ключевые аспекты на примере класса Logger, который логирует вызовы своих специальных функций.

Основные этапы жизненного цикла

  1. Создание объекта:

    • Конструкторы: Вызываются при создании объекта. Могут быть параметризованными, копирующими или перемещающими.

    • Автоматические объекты (на стеке): Уничтожаются автоматически при выходе из области видимости.

    • Динамические объекты (в куче): Создаются через new, уничтожаются вручную через delete.

    Пример:

    Logger x1; // Вызов конструктора без аргументов

    Logger* x2 = new Logger(1); // Динамический объект

    delete x2; // Вызов деструктора

  2. Копирование и присваивание:

    • Конструктор копирования: Создает новый объект как копию существующего.

    • Оператор присваивания: Модифицирует существующий объект.

    • По умолчанию компилятор генерирует тривиальные версии этих функций.

    Пример:

    Logger x3 = x1; // Конструктор копирования

    x3 = x1; // Оператор присваивания

  3. Перемещение:

    • Конструктор перемещения и оператор присваивания перемещением позволяют эффективно передавать ресурсы временных объектов.

    • Используются с std::move для явного указания перемещения.

    Пример:

    Logger x4 = std::move(x1); // Конструктор перемещения

    x4 = Logger(); // Оператор присваивания перемещением

  4. Деструктор: Вызывается при уничтожении объекта. Для автоматических объектов — при выходе из области видимости, для динамических — при вызове delete.

Особенности работы с классами

  • Статические поля: Общие для всех объектов класса. Используются для подсчета созданных экземпляров или хранения общих данных.

    class Logger {

    inline static int counter = 0; // Статическое поле

    const int id;

    public:

    Logger() : id(++counter) {} // Инициализация id };

  • Композиция классов: При создании объекта сначала инициализируются его поля, затем тело конструктора. Деструкторы вызываются в обратном порядке.

    class OuterLogger {

    Logger inner1, inner2; // Поля инициализируются до тела конструктора

    public: OuterLogger() { /* ... */ }

    ~OuterLogger() { /* ... */ } // Деструкторы inner2, inner1 вызываются после };

Временные объекты и контейнеры

  • Временные объекты существуют до конца выражения. Могут быть переданы в функции через rvalue-ссылки (&&), что позволяет избежать копирования.

    void f(Logger&& x); // Перегрузка для временных объектов

    f(Logger()); // Вызов версии с перемещением

  • Контейнеры (например, std::vector, std::list) управляют памятью автоматически. При реаллокации элементы могут копироваться или перемещаться.

    std::vector<Logger> vec;

    vec.emplace_back(); // Создание объекта напрямую в контейнере

    vec.push_back(Logger()); // Создание временного объекта и его перемещение

Понимание жизненного цикла объектов помогает управлять ресурсами, избегать утечек и оптимизировать производительность.

1. Реализация класса Logger

Создайте класс Logger со следующими требованиями:

  • Имеет static int counter для подсчета созданных объектов.

  • Содержит const int id, инициализируемую в конструкторе через ++counter.

  • Реализуйте:

    • Конструктор по умолчанию (логирует "Constructor called, id=X").

    • Конструктор копирования (логирует "Copy constructor, id=X → Y").

    • Конструктор перемещения (логирует "Move constructor, id=X → Y").

    • Деструктор (логирует "Destructor, id=X").

    • Операторы присваивания (копирования и перемещения) с аналогичным логированием.

Цель: Научиться реализовывать все специальные функции класса.


2. Проверка порядка деструкторов

Создайте класс Composite, содержащий два поля типа Logger:

class Composite { Logger logger1; Logger logger2; public: Composite() { /* ... */ } };

  • В конструкторе Composite добавьте вывод "Composite constructor".

  • В деструкторе — "Composite destructor".

  • Создайте объект Composite в области видимости функции и определите порядок вызова деструкторов.

Цель: Понять порядок инициализации и уничтожения полей класса.


3. Временные объекты и перемещение

Напишите функцию:

void processLogger(Logger&& tempLogger) { std::cout << "Processing temporary logger" << std::endl; }

  • Создайте временный объект Logger() и передайте его в processLogger.

  • Объясните, почему не вызывается конструктор копирования.

Цель: Закрепить работу с rvalue-ссылками и перемещением.


4. Контейнеры и реаллокация

  • Создайте std::vector<Logger>.

  • Добавьте в него 3 элемента через push_back и emplace_back.

  • Запустите программу и объясните:

    • Почему при push_back(Logger()) вызывается перемещающий конструктор.

    • Как emplace_back позволяет избежать лишних вызовов конструкторов.

    • Что происходит при реаллокации вектора?

Цель: Изучить работу с контейнерами и оптимизацию через перемещение.


5. Динамические объекты и умные указатели

  • Создайте динамический объект Logger* dynamicLogger = new Logger();.

  • Удалите его через delete.

  • Перепишите код с использованием std::unique_ptr<Logger>.

  • Объясните, как умные указатели предотвращают утечки памяти.

Цель: Научиться управлять динамической памятью.


6. Запрет копирования

Модифицируйте класс Logger:

  • Удалите конструктор копирования и оператор присваивания.

  • Проверьте, что код Logger a; Logger b = a; вызывает ошибку компиляции.

Цель: Понять, как ограничивать жизненный цикл объектов.


7. Наследование и порядок вызовов

Создайте класс DerivedLogger : public Logger:

  • Добавьте поле Logger memberLogger.

  • В конструкторе и деструкторе DerivedLogger добавьте логирование.

  • Создайте объект DerivedLogger и зафиксируйте порядок вызовов конструкторов и деструкторов.

Цель: Изучить жизненный цикл объектов при наследовании.


8. Анализ кода

Дан код:

Logger createLogger() { return Logger(); } int main() { Logger a; Logger b = a; Logger c = std::move(createLogger()); std::vector<Logger> vec; vec.push_back(Logger()); return 0; }

  • Предскажите, сколько раз вызываются конструкторы (копирования, перемещения) и деструкторы.

  • Проверьте свой ответ, добавив логирование в класс Logger.

Цель: Научиться анализировать жизненный цикл объектов в реальном коде.

Показать полностью
[моё] Гайд Программирование IT C++ Windows Длиннопост
1
5
mcnikirikitiki
4 месяца назад
Лига программистов

Основы программирования на C++: Классы⁠⁠

Прежде чем читать мою статью - реши для себя, зачем ты это делаешь. Даже если ты просто нормальный человек, лишним не будет.

Если вы настоящий профессионал программирования, то зачем вы тут сидите и читайте статью на пикабу? Если вы ради интереса зашли почитать, то претензий ноль, но если вы просто захотели задушить нового пользователя Пикабу минусами, то немедленно покиньте статью, вам однозначно интересно не будет.

Здравствуйте, мои маленькие любители программирования!

Классы и их особенности

Классы в программировании похожи на структуры: они представляют собой пользовательские типы данных, которые содержат поля. Синтаксически ключевые слова struct и class взаимозаменяемы, однако между ними есть важное различие. В struct поля по умолчанию являются публичными, а в class — приватными. Мы будем использовать эти термины для обозначения разных подходов к организации данных.

  • Структуры (struct) используются, когда нам не требуется сложная логика для работы с данными. Это просто набор полей без каких-либо ограничений. Пример: структура Point, которая хранит координаты.

  • Классы (class) применяются, когда необходимо контролировать данные, обеспечивать их корректность и выполнять определённые действия при инициализации или изменении. Например, класс Time гарантирует, что время всегда находится в допустимых пределах.

Классы не только задают тип данных, но и определяют их поведение. Переменные такого типа называются объектами.


Объявление класса

Рассмотрим пример простой структуры, которая хранит время в часах, минутах и секундах:

struct Time {

int hours = 0;

int minutes = 0;

int seconds = 0;

};

Эта структура удобна, но она не проверяет корректность значений. Например, можно присвоить часам значение 42, а минутам — -5. Чтобы избежать таких ошибок, объявим класс Time.

В классе поля будут находиться в приватной области, доступ к которой ограничен. Публичная часть будет содержать конструктор для инициализации и методы для чтения значений:

class Time {

private:

int hours;

int minutes;

int seconds;

public:

Time(int h, int m, int s); // Конструктор

int GetHours() const; // Метод для получения часов

int GetMinutes() const; // Метод для получения минут

int GetSeconds() const; // Метод для получения секунд

};

Здесь конструктор отвечает за начальную инициализацию объекта, а методы GetHours, GetMinutes и GetSeconds объявлены как константные (с пометкой const), что означает их невозможность изменять состояние объекта.


Реализация функций

Теперь реализуем объявленные функции. Для этого можно написать их тела внутри класса или отдельно. При внешнем определении используется префикс с именем класса и двоеточием:

Time::Time(int h, int m, int s) {

if (s < 0 || s > 59) {

// Обработка ошибочных секунд

}

if (m < 0 || m > 59) {

// Обработка ошибочных минут

}

if (h < 0 || h > 23) {

// Обработка ошибочных часов

}

hours = h;

minutes = m;

seconds = s;

}

int Time::GetHours() const {

return hours;

}

int Time::GetMinutes() const {

return minutes;

}

int Time::GetSeconds() const {

return seconds;

}

Обратите внимание, что каждая функция класса работает с текущим объектом, который передаётся неявно. Этот объект доступен через указатель this.


Обработка ошибок в конструкторе

Если конструктор получает некорректные значения, он может либо сгенерировать исключение, либо скорректировать данные. Рассмотрим второй вариант:

Time::Time(int h, int m, int s) {

m += s / 60;

s %= 60;

if (s < 0) {

m -= 1;

s += 60;

}

h += m / 60;

m %= 60;

if (m < 0) {

h -= 1;

m += 60;

}

h %= 24;

if (h < 0) {

h += 24;

}

hours = h;

minutes = m;

seconds = s;

}

Теперь объекты класса Time всегда будут содержать корректное время.


Перегрузка конструкторов

Можно добавить несколько конструкторов для удобства. Например, конструктор без параметров и конструктор, принимающий общее количество секунд:

class Time {

private:

int hours = 0;

int minutes = 0;

int seconds = 0;

public:

Time() = default; // Конструктор по умолчанию

Time(int h, int m, int s); // Основной конструктор

Time(int s): Time(0, 0, s) {} // Делегирующий конструктор

};


Изменение состояния объекта

Чтобы позволить изменять объект после создания, добавим метод AddSeconds:

void AddSeconds(int s) {

seconds += s;

Normalize(); // Корректировка времени

}

Этот метод нельзя вызвать для константного объекта, так как он изменяет состояние.


Перегрузка операторов

Для удобства можно перегрузить операторы, такие как += и +. Например:

Time& operator += (int s) {

seconds += s;

Normalize();

return *this;

}

Time operator + (int s) const {

return Time(hours, minutes, seconds + s);

}

Теперь можно писать t += 40 или t + 20.


Ввод и вывод

Операторы << и >> можно перегрузить для работы с потоками:

std::ostream& operator << (std::ostream& out, const Time& t) {

out << t.GetHours() << ":" << t.GetMinutes() << ":" << t.GetSeconds();

return out;

}

std::istream& operator >> (std::istream& in, Time& t) {

int h, m, s;

char dummy;

in >> h >> dummy >> m >> dummy >> s;

t = Time(h, m, s);

return in;

}

Теперь можно легко читать и выводить время.


Модификация реализации

Интерфейс класса остаётся неизменным, даже если внутренняя реализация меняется. Например, вместо трёх полей (hours, minutes, seconds) можно хранить только одно поле totalSeconds:

class Time {

private:

int totalSeconds;

void Normalize() {

const int secondsInDay = 24 * 60 * 60;

totalSeconds %= secondsInDay;

if (totalSeconds < 0) {

totalSeconds += secondsInDay;

}

}

public:

Time(int h, int m, int s) {

totalSeconds = h * 60 * 60 + m * 60 + s;

Normalize();

}

int GetHours() const {

return totalSeconds / (60 * 60);

}

int GetMinutes() const {

return (totalSeconds / 60) % 60;

}

int GetSeconds() const {

return totalSeconds % 60;

}

};

Это упрощает код, сохраняя совместимость с существующими программами.


Таким образом, классы позволяют создавать надёжные и гибкие типы данных, которые легко модифицировать и расширять.

Задание 1: Класс Point

Создайте класс Point, который представляет точку в двумерном пространстве с координатами (x, y). Реализуйте следующие функциональности:

  1. Приватные поля x и y.

  2. Конструкторы :

    • Конструктор без параметров (инициализирует координаты нулями).

    • Конструктор с двумя параметрами для установки значений x и y.

  3. Методы доступа :

    • GetX() и GetY() для получения значений координат.

    • SetX(int x) и SetY(int y) для изменения значений координат.

  4. Перегрузка операторов :

    • Перегрузите оператор + для сложения двух точек (координаты складываются поэлементно).

    • Перегрузите оператор - для вычитания двух точек.

  5. Дополнительно : добавьте метод DistanceTo(const Point& other), который вычисляет расстояние между текущей точкой и другой точкой.


Задание 2: Класс Fraction

Реализуйте класс Fraction, представляющий дробь вида a/b (где a — числитель, b — знаменатель). Добавьте следующие возможности:

  1. Приватные поля numerator и denominator.

  2. Конструкторы :

    • Конструктор с двумя параметрами для инициализации числителя и знаменателя.

    • Конструктор с одним параметром (знаменатель по умолчанию равен 1).

  3. Методы доступа :

    • GetNumerator() и GetDenominator().

    • Метод Simplify(), который сокращает дробь до несократимой формы (например, 4/8 → 1/2).

  4. Перегрузка операторов :

    • Перегрузите операторы +, -, *, / для выполнения арифметических операций с дробями.

    • Перегрузите операторы сравнения (==, !=, <, >, <=, >=).

  5. Дополнительно : добавьте метод ToDouble(), который возвращает значение дроби как число типа double.


Задание 3: Класс BankAccount

Создайте класс BankAccount, моделирующий банковский счёт. Реализуйте следующие функциональности:

  1. Приватные поля :

    • balance (баланс счёта).

    • accountNumber (номер счёта, строка или целое число).

  2. Конструкторы :

    • Конструктор с начальным балансом и номером счёта.

    • Конструктор без параметров (начальный баланс = 0, номер счёта генерируется автоматически).

  3. Методы :

    • Deposit(double amount) для пополнения счёта.

    • Withdraw(double amount) для снятия денег (с проверкой на достаточность средств).

    • GetBalance() для получения текущего баланса.

  4. Перегрузка операторов :

    • Перегрузите оператор += для пополнения счёта.

    • Перегрузите оператор -= для снятия денег.

  5. Дополнительно : добавьте метод Transfer(BankAccount& other, double amount), который переводит деньги с одного счёта на другой.


Задание 4: Класс Date

Реализуйте класс Date, представляющий дату в формате день-месяц-год. Добавьте следующие возможности:

  1. Приватные поля :

    • day, month, year.

  2. Конструкторы :

    • Конструктор с тремя параметрами для инициализации дня, месяца и года.

    • Конструктор без параметров (текущая дата по умолчанию).

  3. Методы :

    • GetDay(), GetMonth(), GetYear() для получения значений.

    • SetDate(int day, int month, int year) для изменения даты.

    • IsValid() для проверки корректности даты (например, 31 февраля недопустимо).

  4. Перегрузка операторов :

    • Перегрузите оператор ++ для увеличения даты на один день.

    • Перегрузите оператор -- для уменьшения даты на один день.

  5. Дополнительно : добавьте метод DaysBetween(const Date& other), который возвращает количество дней между текущей датой и другой датой.


Задание 5: Класс Matrix

Создайте класс Matrix, представляющий матрицу чисел. Реализуйте следующие функциональности:

  1. Приватные поля :

    • Двумерный массив для хранения элементов матрицы.

    • Размеры матрицы (rows, columns).

  2. Конструкторы :

    • Конструктор с размерами матрицы и начальными значениями элементов.

    • Конструктор без параметров (матрица размером 1x1 с нулевым элементом).

  3. Методы :

    • GetElement(int row, int col) и SetElement(int row, int col, int value) для доступа к элементам.

    • Print() для вывода матрицы на экран.

  4. Перегрузка операторов :

    • Перегрузите оператор + для сложения двух матриц.

    • Перегрузите оператор * для умножения матриц (проверьте совместимость размеров).

  5. Дополнительно : добавьте метод Transpose(), который возвращает транспонированную матрицу.


Задание 6: Класс Student

Создайте класс Student, представляющий студента с информацией о его имени, возрасте и оценках. Реализуйте следующие функциональности:

  1. Приватные поля :

    • name (имя студента).

    • age (возраст студента).

    • grades (массив оценок).

  2. Конструкторы :

    • Конструктор с именем, возрастом и массивом оценок.

    • Конструктор только с именем (остальные поля по умолчанию).

  3. Методы :

    • GetName(), GetAge(), GetGrades() для получения данных.

    • AddGrade(int grade) для добавления новой оценки.

    • AverageGrade() для вычисления средней оценки.

  4. Перегрузка операторов :

    • Перегрузите оператор << для вывода информации о студенте в поток.

    • Перегрузите оператор >> для ввода данных о студенте из потока.

  5. Дополнительно : добавьте метод IsExcellentStudent(), который возвращает true, если средняя оценка >= 4.5.


Задание 7: Класс String

Реализуйте свой собственный класс String, аналогичный стандартному std::string. Добавьте следующие возможности:

  1. Приватные поля :

    • Указатель на массив символов (char*).

    • Длина строки.

  2. Конструкторы :

    • Конструктор с C-style строкой (например, "Hello").

    • Конструктор без параметров (пустая строка).

  3. Методы :

    • Length() для получения длины строки.

    • Concat(const String& other) для конкатенации строк.

    • Substring(int start, int length) для получения подстроки.

  4. Перегрузка операторов :

    • Перегрузите оператор + для конкатенации строк.

    • Перегрузите оператор == для сравнения строк.

  5. Дополнительно : реализуйте метод Find(char c), который возвращает индекс первого вхождения символа в строку.

Показать полностью
[моё] IT Программирование C++ Windows Программист Длиннопост
2
Посты не найдены
О нас
О Пикабу Контакты Реклама Сообщить об ошибке Сообщить о нарушении законодательства Отзывы и предложения Новости Пикабу Мобильное приложение RSS
Информация
Помощь Кодекс Пикабу Команда Пикабу Конфиденциальность Правила соцсети О рекомендациях О компании
Наши проекты
Блоги Работа Промокоды Игры Курсы
Партнёры
Промокоды Биг Гик Промокоды Lamoda Промокоды Мвидео Промокоды Яндекс Директ Промокоды Отелло Промокоды Aroma Butik Промокоды Яндекс Путешествия Постила Футбол сегодня
На информационном ресурсе Pikabu.ru применяются рекомендательные технологии