Object-Oriented Programming with Custom Classes in C++

Task 1: GUI Component Implementation

button.h

#pragma once
#include <string>
#include <iostream>

class UIWidget {
public:
    UIWidget(const std::string& caption);
    std::string getCaption() const;
    void activate();

private:
    std::string m_caption;
};

UIWidget::UIWidget(const std::string& caption) : m_caption{caption} {}

inline std::string UIWidget::getCaption() const {
    return m_caption;
}

void UIWidget::activate() {
    std::cout << "Widget '" << m_caption << " activated\n";
}

window.h

#pragma once
#include "button.h"
#include <vector>
#include <iostream>

class Frame {
public:
    Frame(const std::string& title);
    void render() const;
    void terminate();
    void appendWidget(const std::string& label);

private:
    std::string m_title;
    std::vector<UIWidget> m_widgets;
};

Frame::Frame(const std::string& title) : m_title{title} {
    m_widgets.emplace_back(UIWidget("exit"));
}

inline void Frame::render() const {
    std::string border(40, '=');
    std::cout << border << "\n";
    std::cout << "Frame title: " << m_title << "\n";
    std::cout << "Contains " << m_widgets.size() << " widgets:\n";
    for (const auto& widget : m_widgets)
        std::cout << widget.getCaption() << " widget\n";
    std::cout << border << "\n";
}

void Frame::terminate() {
    std::cout << "Closing frame '" << m_title << "'\n";
    m_widgets[0].activate();
}

void Frame::appendWidget(const std::string& label) {
    m_widgets.emplace_back(UIWidget(label));
}

main.cpp

#include "window.h"

void runDemo() {
    Frame desktop("Primary Window");
    desktop.appendWidget("expand");
    desktop.render();
    desktop.terminate();
}

int main() {
    std::cout << "Component Composition Demo:\n";
    runDemo();
}

Task 2: Vector Operations Analysis

vector_test.cpp

#include <iostream>
#include <vector>

void display1d(const std::vector<int>& arr) {
    for (const auto& elem : arr)
        std::cout << elem << " ";
    std::cout << "\n";
}

void display2d(const std::vector<std::vector<int>>& matrix) {
    for (const auto& row : matrix) {
        for (const auto& elem : row)
            std::cout << elem << " ";
        std::cout << "\n";
    }
}

void experiment1() {
    std::vector<int> source(5, 99);
    const std::vector<int> copy(source);

    source[0] = -42;
    std::cout << "Source: "; display1d(source);
    std::cout << "Copy: "; display1d(copy);
}

void experiment2() {
    std::vector<std::vector<int>> original{{1, 2}, {3, 4, 5}};
    const std::vector<std::vector<int>> duplicate(original);

    original[0].push_back(99);
    std::cout << "Original:\n"; display2d(original);
    std::cout << "Duplicate:\n"; display2d(duplicate);
}

int main() {
    experiment1();
    experiment2();
}

Task 3: Custom Dynamic Array Class

dynamic_array.h

#pragma once
#include <cassert>

class DynamicArray {
public:
    DynamicArray(size_t capacity);
    DynamicArray(size_t capacity, int initialValue);
    DynamicArray(const DynamicArray& other);
    ~DynamicArray();

    int& getElement(size_t index);
    const int& getElement(size_t index) const;
    
    DynamicArray& operator=(const DynamicArray& source);
    size_t getSize() const;

private:
    size_t m_size;
    int* m_data;
};

DynamicArray::DynamicArray(size_t capacity) 
    : m_size{capacity}, m_data{new int[m_size]} {}

DynamicArray::DynamicArray(size_t capacity, int initialValue) 
    : m_size{capacity}, m_data{new int[m_size]} {
    for (size_t i = 0; i < m_size; ++i)
        m_data[i] = initialValue;
}

DynamicArray::DynamicArray(const DynamicArray& source) 
    : m_size{source.m_size}, m_data{new int[m_size]} {
    for (size_t i = 0; i < m_size; ++i)
        m_data[i] = source.m_data[i];
}

DynamicArray::~DynamicArray() {
    delete[] m_data;
}

const int& DynamicArray::getElement(size_t index) const {
    assert(index < m_size);
    return m_data[index];
}

int& DynamicArray::getElement(size_t index) {
    assert(index < m_size);
    return m_data[index];
}

DynamicArray& DynamicArray::operator=(const DynamicArray& source) {
    if (this != &source) {
        delete[] m_data;
        m_size = source.m_size;
        m_data = new int[m_size];
        for (size_t i = 0; i < m_size; ++i)
            m_data[i] = source.m_data[i];
    }
    return *this;
}

size_t DynamicArray::getSize() const {
    return m_size;
}

test.cpp

#include "dynamic_array.h"
#include <iostream>

void showArray(const DynamicArray& arr) {
    for (size_t i = 0; i < arr.getSize(); ++i)
        std::cout << arr.getElement(i) << " ";
    std::cout << "\n";
}

void testOperations() {
    DynamicArray arr1(5);
    for (size_t i = 0; i < arr1.getSize(); ++i)
        arr1.getElement(i) = i * i;
    
    DynamicArray arr2(5, 7);
    DynamicArray arr3(arr2);
    arr2.getElement(0) = -100;
    
    showArray(arr1);
    showArray(arr2);
    showArray(arr3);
}

int main() {
    testOperations();
    return 0;
}

Task 4: Matrix Class Implementation

matrix.h

#pragma once
#include <cassert>

class Matrix {
public:
    Matrix(size_t rows, size_t cols);
    Matrix(size_t dimension);
    Matrix(const Matrix& other);
    ~Matrix();

    void populate(const double* source);
    void reset();
    
    double& access(size_t row, size_t col);
    const double& access(size_t row, size_t col) const;
    
    size_t rowCount() const;
    size_t colCount() const;
    void print() const;

private:
    size_t m_rows;
    size_t m_cols;
    double* m_buffer;
};

Matrix::Matrix(size_t rows, size_t cols) 
    : m_rows{rows}, m_cols{cols}, m_buffer{new double[rows * cols]} {
    reset();
}

Matrix::Matrix(size_t dimension) 
    : m_rows{dimension}, m_cols{dimension}, m_buffer{new double[dimension * dimension]} {
    reset();
}

Matrix::Matrix(const Matrix& other) 
    : m_rows{other.m_rows}, m_cols{other.m_cols}, 
      m_buffer{new double[m_rows * m_cols]} {
    for (size_t i = 0; i < m_rows * m_cols; ++i)
        m_buffer[i] = other.m_buffer[i];
}

Matrix::~Matrix() {
    delete[] m_buffer;
}

void Matrix::populate(const double* source) {
    assert(source);
    for (size_t i = 0; i < m_rows * m_cols; ++i)
        m_buffer[i] = source[i];
}

void Matrix::reset() {
    for (size_t i = 0; i < m_rows * m_cols; ++i)
        m_buffer[i] = 0.0;
}

double& Matrix::access(size_t row, size_t col) {
    assert(row < m_rows && col < m_cols);
    return m_buffer[row * m_cols + col];
}

const double& Matrix::access(size_t row, size_t col) const {
    assert(row < m_rows && col < m_cols);
    return m_buffer[row * m_cols + col];
}

size_t Matrix::rowCount() const { return m_rows; }
size_t Matrix::colCount() const { return m_cols; }

void Matrix::print() const {
    for (size_t i = 0; i < m_rows; ++i) {
        for (size_t j = 0; j < m_cols; ++j)
            std::cout << m_buffer[i * m_cols + j] << " ";
        std::cout << "\n";
    }
}

demo.cpp

#include "matrix.h"
#include <iostream>

int main() {
    double data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    
    Matrix m1(3, 3);
    m1.populate(data);
    m1.print();
    
    Matrix m2(m1);
    m2.access(0, 0) = 999;
    std::cout << "\nAfter modification:\n";
    m2.print();
    
    return 0;
}

Task 5: User Account Management

user.h

#pragma once
#include <string>
#include <iomanip>

class Profile {
public:
    Profile(const std::string& username, 
            const std::string& passcode = "123456", 
            const std::string& email = "user@example.com");
    
    void updateEmail();
    void updatePassword();
    void showInfo() const;

private:
    std::string m_username;
    std::string m_passcode;
    std::string m_email;
};

Profile::Profile(const std::string& username, 
                 const std::string& passcode, 
                 const std::string& email)
    : m_username{username}, m_passcode{passcode}, m_email{email} {}

void Profile::updateEmail() {
    std::string newEmail;
    while (true) {
        std::cout << "Enter new email: ";
        std::cin >> newEmail;
        if (newEmail.find('@') != std::string::npos) {
            m_email = newEmail;
            std::cout << "Email updated successfully.\n";
            break;
        }
        std::cout << "Invalid email format. Try again.\n";
    }
}

void Profile::updatePassword() {
    std::string current;
    int attempts = 0;
    
    while (attempts < 3) {
        std::cout << "Enter current password: ";
        std::cin >> current;
        
        if (current == m_passcode) {
            std::cout << "Enter new password: ";
            std::cin >> m_passcode;
            std::cout << "Password updated successfully.\n";
            return;
        }
        std::cout << "Incorrect password. ";
        attempts++;
    }
    std::cout << "Too many failed attempts. Try later.\n";
}

void Profile::showInfo() const {
    std::cout << std::left << std::setw(12) << "Username:" << m_username << "\n";
    std::cout << std::left << std::setw(12) << "Password:" 
              << std::string(m_passcode.length(), '*') << "\n";
    std::cout << std::left << std::setw(12) << "Email:" << m_email << "\n";
}

Task 6: Banking System Implementation

date.h

#pragma once
class CalendarDate {
private:
    int year_;
    int month_;
    int day_;
    int dayCount_;
    
    bool isLeap() const;
    int daysInMonth() const;
    void calculateDayCount();
    
public:
    CalendarDate(int y, int m, int d);
    
    int getYear() const { return year_; }
    int getMonth() const { return month_; }
    int getDay() const { return day_; }
    
    void display() const;
    int daysBetween(const CalendarDate& other) const;
};

date.cpp

#include "date.h"
#include <iostream>
#include <stdexcept>

namespace {
    const int monthDays[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
}

bool CalendarDate::isLeap() const {
    return (year_ % 4 == 0 && year_ % 100 != 0) || year_ % 400 == 0;
}

int CalendarDate::daysInMonth() const {
    if (month_ == 2) return isLeap() ? 29 : 28;
    if (month_ == 4 || month_ == 6 || month_ == 9 || month_ == 11) return 30;
    return 31;
}

void CalendarDate::calculateDayCount() {
    if (day_ < 1 || day_ > daysInMonth()) {
        throw std::invalid_argument("Invalid date components");
    }
    
    int years = year_ - 1;
    dayCount_ = years * 365 + years / 4 - years / 100 + years / 400;
    dayCount_ += monthDays[month_ - 1] + day_;
    if (month_ > 2 && isLeap()) dayCount_++;
}

CalendarDate::CalendarDate(int y, int m, int d) 
    : year_{y}, month_{m}, day_{d} {
    calculateDayCount();
}

void CalendarDate::display() const {
    std::cout << year_ << "-" << month_ << "-" << day_;
}

int CalendarDate::daysBetween(const CalendarDate& other) const {
    return dayCount_ - other.dayCount_;
}

account.h

#pragma once
#include "date.h"
#include <string>

class SavingsAccount {
private:
    std::string accountId_;
    double balance_;
    double interestRate_;
    CalendarDate lastUpdate_;
    double accumulated_;
    static double globalTotal_;
    
    void recordTransaction(const CalendarDate& date, double amount, const std::string& desc);
    void showError(const std::string& msg) const;
    double calculateAccumulation(const CalendarDate& date) const;
    
public:
    SavingsAccount(const CalendarDate& date, const std::string& id, double rate);
    
    const std::string& getId() const { return accountId_; }
    double getBalance() const { return balance_; }
    double getRate() const { return interestRate_; }
    static double getGlobalTotal() { return globalTotal_; }
    
    void deposit(const CalendarDate& date, double amount, const std::string& desc);
    void withdraw(const CalendarDate& date, double amount, const std::string& desc);
    void applyInterest(const CalendarDate& date);
    void display() const;
};

account.cpp

#include "account.h"
#include <iostream>
#include <cmath>

double SavingsAccount::globalTotal_ = 0;

SavingsAccount::SavingsAccount(const CalendarDate& date, const std::string& id, double rate)
    : accountId_{id}, balance_{0}, interestRate_{rate}, 
      lastUpdate_{date}, accumulated_{0} {
    date.display();
    std::cout << "\tAccount " << id << " created\n";
}

void SavingsAccount::recordTransaction(const CalendarDate& date, double amount, const std::string& desc) {
    accumulated_ = calculateAccumulation(date);
    lastUpdate_ = date;
    
    amount = std::round(amount * 100) / 100;
    balance_ += amount;
    globalTotal_ += amount;
    
    date.display();
    std::cout << "\t" << accountId_ << "\t" << amount 
              << "\t" << balance_ << "\t" << desc << "\n";
}

void SavingsAccount::showError(const std::string& msg) const {
    std::cout << "Error[" << accountId_ << "]: " << msg << "\n";
}

double SavingsAccount::calculateAccumulation(const CalendarDate& date) const {
    return accumulated_ + balance_ * date.daysBetween(lastUpdate_);
}

void SavingsAccount::deposit(const CalendarDate& date, double amount, const std::string& desc) {
    recordTransaction(date, amount, desc);
}

void SavingsAccount::withdraw(const CalendarDate& date, double amount, const std::string& desc) {
    if (amount > balance_) {
        showError("Insufficient funds");
    } else {
        recordTransaction(date, -amount, desc);
    }
}

void SavingsAccount::applyInterest(const CalendarDate& date) {
    double interest = calculateAccumulation(date) * interestRate_ / 365;
    if (interest != 0) {
        recordTransaction(date, interest, "interest");
    }
    accumulated_ = 0;
}

void SavingsAccount::display() const {
    std::cout << "Account: " << accountId_ 
              << "\tBalance: " << balance_;
}

Tags: C++ Object-Oriented Programming Class Design Memory Management Data Structures

Posted on Sat, 09 May 2026 22:08:20 +0000 by ady01