작업 1: GUI 요소의 조합 설계
이 작업은 C++에서 버튼과 창을 모델링하여 간단한 GUI를 시뮬레이션합니다. Button 클래스는 레이블을 가지고 클릭 시 메시지를 출력하며, Window 클래스는 여러 개의 버튼을 포함하는 조합 관계를 가집니다.
핵심 코드
#include <iostream>
#include <string>
#include <vector>
class Button {
public:
explicit Button(const std::string& label);
const std::string& get_label() const;
void click();
private:
std::string label_;
};
Button::Button(const std::string& label) : label_{label} {}
const std::string& Button::get_label() const {
return label_;
}
void Button::click() {
std::cout << "Button '" << label_ << "' activated\n";
}
class Window {
public:
explicit Window(const std::string& title);
void show() const;
void terminate();
void add_button(const std::string& label);
void trigger(const std::string& label);
private:
bool contains(const std::string& label) const;
private:
std::string title_;
std::vector<Button> controls;
};
Window::Window(const std::string& title) : title_{title} {
controls.emplace_back("close");
}
void Window::show() const {
std::string border(40, '=');
std::cout << border << "\n";
std::cout << "window: " << title_ << "\n";
int idx = 0;
for (const auto& btn : controls)
std::cout << ++idx << ". " << btn.get_label() << "\n";
std::cout << border << "\n";
}
void Window::terminate() {
std::cout << "closing window '" << title_ << "'\n";
trigger("close");
}
bool Window::contains(const std::string& label) const {
return std::any_of(controls.begin(), controls.end(),
[&](const Button& b) { return b.get_label() == label; });
}
void Window::add_button(const std::string& label) {
if (contains(label))
std::cout << "duplicate button: " << label << "\n";
else
controls.emplace_back(label);
}
void Window::trigger(const std::string& label) {
auto it = std::find_if(controls.begin(), controls.end(),
[&](const Button& b) { return b.get_label() == label; });
if (it != controls.end())
it->click();
else
std::cout << "missing button: " << label << "\n";
}
실행 예제
int main() {
std::cout << "GUI 시뮬레이션 시작:\n";
Window win{"메인"};
win.add_button("추가");
win.add_button("삭제");
win.add_button("수정");
win.add_button("추가"); // 중복
win.show();
win.terminate();
return 0;
}
작업 2: 벡터의 깊은 복사 검증
이 섹션에서는 std::vector의 복사 생성자가 얕은 복사가 아닌 깊은 복사를 수행함을 입증합니다. 내부 데이터가 독립적으로 유지되므로 한 객체의 수정이 다른 객체에 영향을 주지 않습니다.
void test_deep_copy() {
std::vector<int> src(5, 99);
const std::vector<int> dst(src); // 깊은 복사
std::cout << "src: ";
for (const auto& e : src) std::cout << e << " ";
std::cout << "\ndst: ";
for (const auto& e : dst) std::cout << e << " ";
src[0] = -5;
std::cout << "\nsrc[0] 변경 후:\n";
std::cout << "src: " << src[0] << ", dst: " << dst[0] << "\n"; // dst[0] == 99
}
작업 3: 사용자 정의 정수 벡터 클래스
vectorInt 클래스는 동적 배열 기반의 컨테이너로, 복사 생성자와 대입 연산자를 통해 안전한 메모리 관리를 제공합니다.
class vectorInt {
public:
vectorInt();
vectorInt(int size);
vectorInt(int size, int value);
vectorInt(const vectorInt& other);
~vectorInt();
int size() const;
int& at(int index);
const int& at(int index) const;
vectorInt& operator=(const vectorInt& other);
int* begin();
int* end();
const int* begin() const;
const int* end() const;
private:
int count;
int* data;
};
// const 멤버 함수 재사용을 위한 const_cast 활용
int& vectorInt::at(int index) {
return const_cast<int&>(static_cast<const vectorInt*>(this)->at(index));
}
작업 4: 행렬 클래스 설계
Matrix 클래스는 2차원 배열을 모델링하며, 요소 접근, 초기화, 출력 등의 기능을 제공합니다.
class Matrix {
public:
Matrix(int rows, int cols, double val = 0.0);
Matrix(const Matrix& other);
~Matrix();
void set(const double* values, int length);
void clear();
double& at(int i, int j);
const double& at(int i, int j) const;
void print() const;
int rows() const;
int cols() const;
private:
int rows_, cols_;
double* buffer;
};
작업 5: 연락처 관리 시스템
ContactBook 클래스는 이름 기준으로 정렬된 연락처 목록을 관리하며, 추가, 삭제, 검색 기능을 제공합니다.
class ContactBook {
public:
void add(const std::string& name, const std::string& phone);
void remove(const std::string& name);
void find(const std::string& name) const;
void display() const;
private:
int find_index(const std::string& name) const;
void sort_by_name();
std::vector<Contact> entries;
};
void ContactBook::sort_by_name() {
std::sort(entries.begin(), entries.end(),
[](const Contact& a, const Contact& b) {
return a.get_name() < b.get_name();
});
}