Загрузка данных


#include <iostream>
#include <string>
#include <cstring>
#include <stdexcept>

// ==========================================
// 1. Класс "Жесткий диск"
// ==========================================
class HardDisk {
private:
    int volume; // объем в Мбайт (скрытое поле)

public:
    // Конструктор по умолчанию
    HardDisk() : volume(512) {}

    // Конструктор с параметром
    HardDisk(int vol) {
        setVolume(vol);
    }

    // Свойство / метод доступа для объема
    void setVolume(int vol) {
        if (vol <= 0) {
            throw std::invalid_argument("Ошибка: объем жесткого диска должен быть положительным числом!");
        }
        volume = vol;
    }

    int getVolume() const {
        return volume;
    }

    // Функция печати
    void print() const {
        std::cout << "Жесткий диск: " << volume << " Мбайт";
    }
};

// ==========================================
// 2. Базовый класс "Компьютер"
// ==========================================
class Computer {
private:
    char* brand;       // марка (указатель на строку)
    double price;      // цена
    HardDisk hardDisk; // композиция: класс содержит объект жесткого диска

public:
    // Конструктор по умолчанию
    Computer() : price(0.0), hardDisk() {
        brand = new char[1];
        brand[0] = '\0';
    }

    // Конструктор с параметрами
    Computer(const char* b, double p, const HardDisk& hd) : price(0.0), hardDisk(hd) {
        setBrand(b);
        setPrice(p);
    }

    // Конструктор копирования (глубокое копирование для динамической памяти)
    Computer(const Computer& other) : price(other.price), hardDisk(other.hardDisk), brand(nullptr) {
        if (other.brand) {
            brand = new char[strlen(other.brand) + 1];
            strcpy(brand, other.brand);
        }
    }

    // Оператор присваивания
    Computer& operator=(const Computer& other) {
        if (this == &other) return *this;
        
        price = other.price;
        hardDisk = other.hardDisk;

        char* newBrand = nullptr;
        if (other.brand) {
            newBrand = new char[strlen(other.brand) + 1];
            strcpy(newBrand, other.brand);
        }

        delete[] brand;
        brand = newBrand;
        return *this;
    }

    // Деструктор (очистка динамической памяти)
    virtual ~Computer() {
        delete[] brand;
    }

    // Свойства и методы доступа с проверкой исключений
    void setBrand(const char* b) {
        if (!b) {
            throw std::invalid_argument("Ошибка: указатель на строку марки не может быть нулевым!");
        }
        char* temp = new char[strlen(b) + 1];
        strcpy(temp, b);
        delete[] brand;
        brand = temp;
    }

    const char* getBrand() const {
        return brand;
    }

    void setPrice(double p) {
        if (p < 0.0) {
            throw std::out_of_range("Ошибка: цена компьютера не может быть отрицательной!");
        }
        price = p;
    }

    double getPrice() const {
        return price;
    }

    void setHardDisk(const HardDisk& hd) {
        hardDisk = hd;
    }

    const HardDisk& getHardDisk() const {
        return hardDisk;
    }

    // Виртуальная функция печати
    virtual void print() const {
        std::cout << "Марка: " << (brand[0] != '\0' ? brand : "Не указана") 
                  << ", Цена: " << price << " руб. | ";
        hardDisk.print();
    }
};

// ==========================================
// 3. Публично производный класс "Компьютер с монитором"
// ==========================================
class PublicComputerWithMonitor : public Computer {
private:
    double monitorSize; // размер монитора (в дюймах)

public:
    PublicComputerWithMonitor() : Computer(), monitorSize(15.6) {}

    PublicComputerWithMonitor(const char* b, double p, const HardDisk& hd, double mSize)
        : Computer(b, p, hd) {
        setMonitorSize(mSize);
    }

    ~PublicComputerWithMonitor() override {
        // Деструктор дочернего класса (базовый деструктор вызывается автоматически)
    }

    void setMonitorSize(double mSize) {
        if (mSize <= 0.0) {
            throw std::invalid_argument("Ошибка: размер монитора должен быть больше 0!");
        }
        monitorSize = mSize;
    }

    double getMonitorSize() const {
        return monitorSize;
    }

    void print() const override {
        std::cout << "[Public Inheritance] ";
        Computer::print();
        std::cout << ", Размер монитора: " << monitorSize << "\"" << std::endl;
    }
};

// ==========================================
// 4. Приватно производный класс "Компьютер с монитором"
// ==========================================
class PrivateComputerWithMonitor : private Computer {
private:
    double monitorSize;

public:
    PrivateComputerWithMonitor() : Computer(), monitorSize(17.0) {}

    PrivateComputerWithMonitor(const char* b, double p, const HardDisk& hd, double mSize)
        : Computer(b, p, hd) {
        setMonitorSize(mSize);
    }

    ~PrivateComputerWithMonitor() override {}

    void setMonitorSize(double mSize) {
        if (mSize <= 0.0) {
            throw std::invalid_argument("Ошибка: размер монитора должен быть больше 0!");
        }
        monitorSize = mSize;
    }

    double getMonitorSize() const {
        return monitorSize;
    }

    // При приватномследовании интерфейс базового класса закрыт снаружи,
    // поэтому мы реализуем собственную функцию печати, обращаясь к методам базового класса внутри.
    void print() const {
        std::cout << "[Private Inheritance] Марка: " << (getBrand() ? getBrand() : "N/A")
                  << ", Цена: " << getPrice() << " руб. | ";
        getHardDisk().print();
        std::cout << ", Размер монитора: " << monitorSize << "\"" << std::endl;
    }
};

// ==========================================
// Главная функция (демонстрация работы)
// ==========================================
int main() {
    // Установка русской локали для корректного вывода в консоль
    std::setlocale(LC_ALL, "Russian");

    std::cout << "=== 1. Демонстрация штатной работы классов ===" << std::endl;
    try {
        HardDisk myHd(1024);
        Computer baseComp("ASUS", 75000.0, myHd);
        baseComp.print();
        std::cout << std::endl;

        PublicComputerWithMonitor pubComp("MSI", 120000.0, HardDisk(2048), 27.0);
        pubComp.print();

        PrivateComputerWithMonitor privComp("Lenovo", 55000.0, HardDisk(512), 23.8);
        privComp.print();
    }
    catch (const std::exception& e) {
        std::cerr << "Поймано исключение: " << e.what() << std::endl;
    }

    std::cout << "\n=== 2. Демонстрация обработки исключений ===" << std::endl;

    // Проверка исключения для жесткого диска
    try {
        std::cout << "Попытка создать жесткий диск с неверным объемом (-500 МБ)..." << std::endl;
        HardDisk invalidHd(-500);
    }
    catch (const std::exception& e) {
        std::cerr << "Перехвачено исключение: " << e.what() << std::endl;
    }

    // Проверка исключения для цены компьютера
    try {
        std::cout << "\nПопытка задать отрицательную цену компьютера (-1000 руб.)..." << std::endl;
        Computer comp;
        comp.setPrice(-1000.0);
    }
    catch (const std::exception& e) {
        std::cerr << "Перехвачено исключение: " << e.what() << std::endl;
    }

    // Проверка исключения для размера монитора
    try {
        std::cout << "\nПопытка создать монитор с нулевым размером..." << std::endl;
        PublicComputerWithMonitor invalidMonitor("HP", 40000.0, HardDisk(512), 0.0);
    }
    catch (const std::exception& e) {
        std::cerr << "Перехвачено исключение: " << e.what() << std::endl;
    }

    return 0;
}