Aura 프로젝트를 진행하면서 C++에 대한 지식을 생각보다 얕게 가지고 있었다.
특히 Class가 자주 사용되는데 어떻게 사용되는건지 이해를 확실히 하고 넘어가야겠다고
프로젝트 하면서 자주 느끼게 되어 클래스에 대해 알아보았다.
클래스(Class)란?
C++에서 클래스는 데이터와 해당 데이터를 조작하는 함수를 하나의 단위로 묶어주는 기능을 제공한다.
클래스는 객체지향 프로그래밍의 핵심 개념 중 하나이며,
코드의 구조화, 재사용성 및 유지보수성을 향상시키는 데 사용된다.
간단한 C++ 클래스 예시를 확인해보자.
#include <iostream>
// 클래스 정의
class Rectangle {
private:
int width;
int height;
public:
// 생성자
Rectangle(int w, int h) {
width = w;
height = h;
}
// 멤버 함수
int area() {
return width * height;
}
};
int main() {
// 객체 생성
Rectangle rect(5, 10);
// 멤버 함수 호출
std::cout << "사각형의 넓이: " << rect.area() << std::endl;
return 0;
}
위 코드에서 'Rectangle' 클래스는 사각형을 나타내며,
'width' 와 'height' 라는 두 개의 멤버 변수를 가지고 있다.
이러한 구조를 보고 구조체와 비슷하게 느껴졌다.
그래서 구조체와 어떤 차이를 가지고 있는지도 한번 알아보았다.
구조체와 클래스의 차이
이 둘은 서로 비슷한 기능을 가지고 있지만 몇 가지 차이점이 있다.
여기에 각각의 특징을 설명하겠다.
I. 데이터 캡슐화
- 클래스: 멤버 변수와 멤버 함수를 하나의 단위로 묶어 캡슐화하여 정보 은닉을 지원한다. 보통 멤버 변수는 private로 선언되고, 멤버 함수를 통해 접근된다.
- 구조체: 일반적으로 멤버 변수를 public으로 선언하여 외부에서 직접 접근할 수 있다.
II. 기본 접근 제어 수준
- 클래스: 기본적으로 멤버 변수와 멤버 함수의 접근 제어 수준이 private이다.
- 구조체: 기본적으로 멤버 변수와 멤버 함수의 접근 제어 수준이 public이다.
III. 상속
- 클래스: 클래스는 다른 클래스로부터 상속을 받아 새로운 클래스를 정의할 수 있다. 상속을 통해 기존 클래스의 기능을 재사용하고 확장할 수 있습니다.
- 구조체: 구조체는 일반적으로 상속을 지원하지 않습니다. 따라서 구조체는 데이터를 단순하게 그룹화하는 데 사용됩니다.
IV. 가상 함수
- 클래스: 클래스는 가상 함수를 사용하여 다형성(polymorphism)을 지원할 수 있다. 가상 함수는 상속된 클래스에서 재정의될 수 있습니다.
- 구조체: 구조체는 가상 함수를 지원하지 않는.
V. 메모리 할당 방식
- 클래스: 클래스의 인스턴스는 일반적으로 동적으로 할당된다. new 키워드를 사용하여 힙(heap)에 할당됨.
- 구조체: 구조체의 인스턴스는 일반적으로 정적으로 할당되며, 스택(stack)에 할당된다.
VI. 사용 목적
- 클래스: 주로 복잡한 객체지향 프로그래밍을 위해 사용된다. 상속, 다형성 등의 객체지향 개념을 구현하는 데 적합하다.
- 구조체: 주로 간단한 데이터 구조를 표현하기 위해 사용된다. 데이터의 그룹화와 연관된 기능을 제공하기 위해 사용된다.
정리하자면,
간단한 데이터 구조를 표현하고 관련 기능을 제공하기 위해서는 구조체를,
복잡한 객체지향 프로그래밍을 위해서는 클래스를 사용하는 것이 더 적절하다.
예시.
이전 백준에서 풀어본 문제를 클래스 형식으로 리팩토링 하였다.
원래 코드
#include <iostream>
#include <string>
using namespace std;
int N, M;
void count_IO(const string& S)
{
}
int main() {
string S;
// 입력 받기 OOIOIOIOIIOII(13)
cin >> N;
cin >> M;
cin >> S;
int count = 0;
for (int i = 0; i < M; i++)
{
int length = 0;
if (S[i] == 'O')
{
continue;
}
else
{
while (S[i + 1] == 'O' && S[i + 2] == 'I')
{
length++;
if (length == N)
{
count++;
length--;
}
i += 2;
}
}
length = 0;
}
cout << count;
return 0;
}
리팩토링
#include <iostream>
#include <string>
using namespace std;
class StringCheck{
private:
int count = 0; //몇 군데 포함되어있는지 카운트
int length = 0; //length, N의 길이
int PN;
int Length;
string Input;
public:
StringCheck(int N, int M, string S)
{
PN = N;
Length = M;
Input = S;
}
int scan()
{
for (int i = 0; i < Length; i++)
{
//시작 문자가 'O'일 경우, 반복문을 실행하지 않고 다음으로 넘어간다.
//주어진 문자열은 무조건 I로 시작하기 때문
if (Input[i] == 'O')
{
continue;
}
else
{
while (Input[i + 1] == 'O' && Input[i + 2] == 'I')
{
//length에 1을 더한다.
//예를 들면, N = 2은 IOIOI이다, 이는 S[i]이 I, S[i+1]이 O, S[i+2]가 I일 때
//이를 하나로 보고 length에 1을 더한다. if문에 적합하지 않으면 한번 더 반복하여 OI를 카운트 해
//length에 1을 또 더해 length는 2가 된다.
length++;
//N = 2이므로, 카운트를 추가한다.
//length--를 하는 이유는 이미 발견한 패턴에 대해 중복 계산을 방지하기 위한 것.
if (length == PN)
{
count++;
length--;
}
//i에 2를 더해 N의 길이만큼 늘려서 탐색한다.
i += 2;
}
}
length = 0;
}
return count;
}
};
int main() {
int N, M;
string S;
// 입력 받기 OOIOIOIOIIOII(13)
cin >> N; //Pn
cin >> M; //입력 글자 수, 반복문에 사용한다
cin >> S; //입력
StringCheck result(N, M, S);
cout << result.scan();
return 0;
}
확실히 간결한 코드에는 클래스를 사용하지 않는게 좋고,
게임 프로그래밍 같이 복잡한 프로젝트에서는 Class를 자주 사용하는게 좋다는 점을 깨닫게 되었다.
아직 클래스에 대해 조금 미흡한 부분이 있어서, 이전에 풀어본 문제들을 리팩토링하여
어떻게 코드를 구현해야할 지 감을 익혀봐야겠다.
'Etc.' 카테고리의 다른 글
[C++] 포인터 (0) | 2024.05.17 |
---|---|
댕글링 포인터(Dangling Pointer) (0) | 2024.05.16 |
BaekJoon 1931 문제에서.. (0) | 2024.04.09 |
[C++] Vector와 Deque (0) | 2023.09.26 |
C++ 입출력 시간 단축 (0) | 2023.09.19 |