C++ 객체 지향 프로그래밍

윤준혁·2025년 2월 28일

객체지향 프로그래밍(OOP, Object-Oriented Programming)

객체지향 프로그래밍이란?

  • 프로그램을 객체 단위로 구성하여, 코드의 재사용성과 유지보수성을 높이는 프로그래밍 패러다임
  • 객체는 데이터(속성)와 이를 조작하는 함수(메서드)를 포함하는 독립적인 단위로 정의

객체지향 프로그래밍의 원리

추상화(Abstraction)

  • 복잡한 시스템을 단순화하여 필요한 부분만을 표현하는 개념
  • 예를 들어, 자동차를 운전할 때 내부 엔진 작동 방식까지 알 필요 없이 핸들과 페달만 조작하면 되는 개념

캡슐화(Encapsulation)

  • 데이터와 메서드를 하나로 묶어 외부에서 직접 접근하지 못하도록 보호하는 개념
  • 예를 들어, 자동차 내부 엔진은 직접 조작할 수 없으며, 운전자가 조작 가능한 인터페이스만 노출되는 개념

상속(Inheritance)

  • 기존 클래스(부모 클래스)의 속성과 기능을 새로운 클래스(자식 클래스)가 물려받는 개념
  • 예를 들어, Vehicle 클래스에서 Car와 Bike 클래스를 상속받아 공통 기능을 공유할 수 있는 개념

다형성(Polymorphism)

  • 동일한 인터페이스를 가진 여러 개체가 다른 방식으로 동작할 수 있는 개념
  • 예를 들어, Animal 클래스의 makeSound() 메서드가 Dog 클래스에서는 "멍멍"을, Cat 클래스에서는 "야옹"을 출력하는 개념

접근 제한자(Access Specifier)

  • 클래스 멤버에 대한 접근 권한을 설정하는 키워드
    • public : 외부에서도 접근 가능
    • private : 클래스 내부에서만 접근 가능
    • protected : 클래스 내부와 상속받은 클래스에서만 접근 가능
class Example {
private:
    int privateVar;
protected:
    int protectedVar;
public:
    int publicVar;
};

클래스 vs 오브젝트

  • 클래스(Class) : 객체를 정의하는 틀(템플릿)
  • 객체(Object) : 클래스를 기반으로 생성된 실제 인스턴스
class Car { // 클래스
public:
    string brand;
    int year;

    void display() {
        cout << "Brand: " << brand << ", Year: " << year << endl;
    }
};

int main() {
    Car myCar; // 객체 생성
    myCar.brand = "Tesla";
    myCar.year = 2023;
    myCar.display();
}

클래스 생성 - 데이터, 메서드

  • 클래스는 속성(데이터)와 메서드(함수)로 구성된다
class Person {
private:
    string name;
    int age;
public:
    void setName(string n) { name = n; }
    string getName() { return name; }
    void setAge(int a) { age = a; }
    int getAge() { return age; }
};

객체에 포인터를 주는 방법

  • 객체를 가리키는 포인터를 선언하여 사용
Person p1;
Person* pPtr = &p1; // 객체 포인터
pPtr->setName("Alice");
cout << pPtr->getName();

객체에 대한 포인터

  • 객체의 주소를 저장하는 포인터를 이용하여 간접적으로 객체를 조작할 수 있다
Person obj;
Person* ptr = &obj;
ptr->setName("John");
cout << ptr->getName();

Stack, Heap에서 객체를 생성하는 방법

  • Stack : 일반적인 객체 선언 시 스택에 할당
  • Heap : new 연산자로 동적으로 객체를 생성할 경우 할당
Person* pHeap = new Person(); // Heap에 객체 생성
pHeap->setName("Bob");
cout << pHeap->getName();
delete pHeap; // 동적 할당 해제

데이터 은폐와 Property Function

  • 데이터 은폐는 객체 내부의 데이터가 외부에서 직접 접근하지 못하도록 보호하는 개념
  • 이를 위해 접근자 메서드를 사용
class BankAccount {
private:
    double balance;
public:
    double getBalance() { return balance; } // Accessor
    void setBalance(double b) { balance = b; } // Mutator
    void deposit(double amount) { balance += amount; } // Facilitator
    bool isEmpty() { return balance == 0; } // Enquiry
};

생성자(Contructors)

  • C++에서 생성자는 객체가 생성될 때 자동으로 호출되는 특수한 멤버 함수이다

기본 생성자(Default Constructor)

  • 인자가 없는 생성자
class Car {
public:
    string brand;
    Car() { brand = "Unknown"; } // 기본 생성자
};

파라미터 생성자(Parameter Constructor)

  • 인자를 받아 초기화하는 생성자
class Car {
public:
    string brand;
    Car(string b) { brand = b; } // 파라미터 생성자
};

복사 생성자(Copy Constructor)

  • 기존 객체를 복사하여 새 객체를 생성하는 생성자
class Car {
public:
    string brand;
    Car(const Car &c) { brand = c.brand; } // 복사 생성자
};

복사 생성자의 문제점

  • 객체가 직접 메모리를 할당할 경우 복사 생성자는 같은 메모리를 가리켜 문제가 발생할 수 있다
class Test {
private:
    int* data;
public:
    Test(int val) { data = new int(val); }
    Test(const Test& t) { data = t.data; } // 문제 발생 (같은 메모리 공유)
};
  • 해결 방법은 깊은 복사(Deep Copy)를 구현하는 것이다
Test(const Test& t) {
    data = new int(*t.data); // 새로운 메모리 생성
}

Scope Resolution Operator(범위 지정 연산자 ::)

  • 클래스의 멤버 함수를 클래스 외부에서 정의할 때 사용
class Sample {
public:
    void show();
};

void Sample::show() { // 범위 지정 연산자 사용
    cout << "Hello!";
}

인라인 함수(Inline Function)

  • 짧은 함수의 경우 컴파일러가 함수를 호출하지 않고 직접 코드에 삽입하여 실행 속도를 높인다
inline int add(int a, int b) { return a + b; }

this 포인터

  • 현재 객체의 주소를 가리키는 포인터
class Example {
public:
    void display() { cout << this; } // 현재 객체의 주소 출력
};

Struct vs Class

  • Struct : 기본 접근 제한자가 public
  • Class : 기본 접근 제한자가 private

0개의 댓글