[C++][OOP] Class - definition, struct, constructor, destructor

 

객체 지향 프로그래밍의 핵심: 클래스

들어가며

객체 지향 프로그래밍(OOP)은 현대 소프트웨어 개발의 주요 패러다임 중 하나로, 코드 재사용, 유지보수 용이성, 확장성 측면에서 많은 이점을 제공한다. OOP의 핵심 개념은 클래스와 객체이며, 이번 포스팅에서는 클래스에 대해 심층적으로 논의하고자 한다.

클래스: 사용자 정의 타입

클래스는 객체를 생성하기 위한 청사진 또는 템플릿으로, 객체의 속성(데이터)과 행동(메서드)을 정의한다. 즉, 클래스는 사용자가 직접 정의하는 데이터 타입이라고 할 수 있다.

예를 들어, '학생'이라는 객체를 표현하기 위해 Student 클래스를 정의할 수 있다. Student 클래스는 학생의 이름, 학번, 성적과 같은 속성과, 수업 등록, 성적 확인, 정보 수정과 같은 행동을 포함할 수 있다.

정리하면, 클래스에는 다음과 같이 2가지 주요한 요소가 있다.

  1. 속성 (Properties): 객체의 상태를 나타내는 변수들이다. Student 클래스의 경우, name, id, grade 등이 속성이 될 수 있다.
  2. 행동 (Behaviors): 객체가 수행할 수 있는 동작을 나타내는 메서드들이다. Student 클래스의 경우, enrollCourse(), checkGrade(), updateInfo() 등이 행동이 될 수 있다.

객체: 클래스의 인스턴스

객체는 클래스를 기반으로 생성된 실체이다. 즉, 클래스가 청사진이라면 객체는 그 청사진을 바탕으로 만들어진 건물과 같다. 하나의 클래스로부터 여러 개의 객체를 생성할 수 있으며, 각 객체는 고유한 속성 값을 가진다.

예를 들어, Student 클래스를 이용하여 student1이라는 이름의 객체를 생성할 수 있다. student1 객체는 자신의 이름, 학번, 성적 정보를 가진다.

C++에서의 클래스와 구조체

C++에서는 클래스와 유사한 개념으로 구조체(struct)가 있다. 둘 다 데이터와 메서드를 캡슐화할 수 있다는 점에서 유사하지만, 중요한 차이점이 있다. 바로 접근 제어 지시자(Access Specifier)이다.

클래스는 public, private, protected 세 가지 접근 제어 지시자를 사용하여 멤버 변수 및 메서드에 대한 접근을 제한할 수 있다. (default : private)

  • public: 모든 곳에서 접근 가능
  • private: 클래스 내부에서만 접근 가능
  • protected: 클래스 내부 및 파생 클래스에서 접근 가능

반면 구조체는 기본적으로 모든 멤버가 public으로 설정된다. 이러한 차이점은 객체 지향 프로그래밍의 핵심 원리 중 하나인 캡슐화(Encapsulation)를 구현하는 데 중요한 역할을 한다. 캡슐화는 객체의 내부 데이터를 외부로부터 보호하고, 메서드를 통해서만 접근하도록 제한하여 데이터 무결성을 유지하는 것을 의미한다.


struct vs class

위와 같은 code가 있다고 할 때, struct는 오류가 발생하지 않지만, class에서는 오류가 발생한다. 이는 struct의 경우 모든 멤버가 public으로 설정되어 있어 외부에서 값을 직접적으로 initialize할 수 있는 반면, class는 모든 멤버가 기본적으로 private로 설정되어 있어 불가능하다는 점에서 기인한다.

impossible to initialize in class


*참고) Dereferencing - pointer 다시보기

Student student;를 선언하면 student라는 이름의 Student 객체가 스택 메모리에 생성된다. 이때 student는 객체 자체를 나타내는 것이므로, 멤버 변수나 멤버 함수에 접근할 때 . 연산자를 사용한다.

예를 들어, student 객체의 id 멤버 변수에 값을 할당하려면 다음과 같이 작성한다.

C++
student.id = 20230001; 


반면에, Student* studentPtr = new Student(); 와 같이 선언하는 경우는 studentPtr이라는 이름의 포인터 변수가 스택 메모리에 생성되고, 이 포인터 변수가 힙 메모리에 할당된 Student 객체를 가리키게 된다. 이 경우에는 studentPtr이 포인터이므로 멤버 변수나 멤버 함수에 접근할 때 (* object name)이나 -> 연산자를 사용한다.

C++
studentPtr->id = 20230002;

요약하자면,

  • Student student; ➡️ 객체 직접 사용, 스택 메모리 할당, . 연산자 사용
  • Student* studentPtr = new Student(); ➡️ 객체를 포인터로 사용, 힙 메모리 할당, (* object name or -> 연산자 사용

생성자: 객체 초기화

그렇다면 클래스에서 initialize할 방법은 없을까? 물론 존재한다. 클래스는 객체 생성 시 멤버 변수를 초기화하기 위해 생성자(Constructor)를 사용한다. 생성자는 클래스와 이름이 같은 특수한 메서드로, 객체 생성 시 자동으로 호출된다.

C++
class Student {
private:
  int* m_pID;
  string m_name;
public:
  Student(); // 생성자
  Student(int, string); // 생성자 오버로딩
};

Student::Student() {
  m_pID = new int(0);
  m_name = "Alice";
}

Student::Student(int id, string name) {
  m_pID = new int(id);
  m_name = name;
}

위 예제에서 Student 클래스는 두 개의 생성자를 가지고 있다.(생성자 오버로딩) 첫 번째 생성자는 인자 없이 호출되며, m_pID를 0으로, m_name을 "Alice"로 초기화한다. 두 번째 생성자는 정수형 id와 문자열 name을 인자로 받아 m_pIDm_name을 초기화한다.

이렇게 생성자 오버로딩을 한다면 다양한 방식으로 멤버 변수들을 초기화할 수 있다.


소멸자: 객체 소멸 시 자원 해제

소멸자(Destructor)객체가 소멸될 때 자동으로 호출되는 특수한 메서드로, 객체가 사용하던 자원을 해제하는 역할을 한다. 주로 동적으로 할당된 메모리를 해제하거나 파일을 닫는 등의 작업을 수행한다.

C++
class Student {
private:
  int* m_pID;
  string m_name;
public:
  Student();
  ~Student(); // 소멸자
};

Student::Student() {
  m_pID = new int(0);
  m_name = "Alice";
}

Student::~Student() {
  delete m_pID; // m_pID가 가리키는 메모리 해제
}

위 예제에서 ~Student() 소멸자는 생성자에서 동적으로 할당된 m_pID 메모리를 해제한다.

this 포인터

this 포인터는 객체 자신을 가리키는 포인터이다. 멤버 변수와 매개변수의 이름이 같은 경우, this 포인터를 사용하여 멤버 변수임을 명확히 할 수 있다.

C++
class Student {
private:
  int m_id;
public:
  void SetID(int m_id) {
    this->m_id = m_id; // this->m_id는 클래스의 멤버 변수 m_id를 의미
  }
};

마치며

이번 포스팅에서는 객체 지향 프로그래밍의 핵심 개념인 클래스에 대해 알아보았다. 클래스는 객체를 생성하기 위한 템플릿이며, 속성과 행동으로 구성된다. C++에서는 접근 제어 지시자를 사용하여 멤버 변수 및 메서드에 대한 접근을 제한할 수 있으며, 생성자를 통해 객체를 초기화하고 소멸자를 통해 자원을 해제한다. this 포인터는 객체 자신을 가리키는 포인터로, 멤버 변수와 매개변수의 이름이 같은 경우 유용하게 사용된다.



추천글 :

[C++][OOP] Array & Pointer
(https://hyeonb.blogspot.com/2024/09/coop-array-pointer.html)

[C++][OOP] Array & Pointer - dynamic allocation, reference
(https://hyeonb.blogspot.com/2024/10/coop-array-pointer-dynamic-allocation.html)

hyeon_B

안녕하세요! AI 기술을 이용해 더 나은 세상을 만들어 나가고 싶은 과기원생 Hyeon이라고 합니다. 저는 앞으로 인공지능 시대에는 지식을 '활용'하는 능력이 중요해질 것이라고 생각합니다. 대부분의 일들은 인공지능이 뛰어난 모습을 보이지만, 인공지능은 데이터로 부터 연관관계를 학습하기 때문에 지식들을 새로 통합해서 활용하는 능력이 부족합니다. 인공지능이 뉴턴 전에 만들어졌다면 사과가 떨어지는 이유에 대답하지 못했을 것이고, 아인슈타인 전에 만들어졌다면 중력이 어떻게 생기는지 설명하지 못했을 것입니다. 따라서 앞으로 우리는 '본질'을 탐구하고 그 본질로부터 다른 곳에 적용하며 인공지능을 현명하게 활용해야 할 것입니다. 함께 인공지능 시대를 준비합시다!

댓글 쓰기

다음 이전

POST ADS1

POST ADS 2