개요
C++은 객체지향언어로서 데이터를 추상화하여 객체로 만들어 코드의 재사용성을 높이는데에 특화된 언어이다. 여기에는 Class라는 개념이 불가피한데 Class가 어떻게 쓰이는지 한 번 알아보자
1. Class의 정의
Class는 데이터와 이 데이터를 처리하는 함수를 하나로 묶은 사용자 정의 데이터 형식이다. 객체를 생성하기위한 틀로 사용된다.
Class의 구성요소
1. 멤버 변수
2. 멤버 함수
3. 생성자
4. Getter, Setter
class Car {
private:
string brand;
int speed;
public:
Car(string b, int s) {
brand = b;
speed = s;
}
void accelerate() {
speed += 10;
cout << brand << " is accelerating. Speed: " << speed << " km/h" << endl;
}
void brake() {
speed -= 10;
cout << brand << " is braking. Speed: " << speed << " km/h" << endl;
}
void displayInfo() {
cout << "Car Brand: " << brand << ", Speed: " << speed << " km/h" << endl;
}
void setBrand(string brand){
this->brand = brand;
}
void setSpeed(int speed){
this->speed = speed;
}
string getBrand() { return brand; }
int getSpeed() { return speed; }
};
클래스를 정의할 때에는 보통 "생성자", "멤버변수", "멤버함수"를 포함하여 구현한다.
2. 멤버변수
private:
string brand;
int speed;
멤버변수는 클래스 내부에서 선언된 변수로, 객체의 상태를 나타내는 데이터이다.
외부에서 직접적으로 접근하지 못 하도록 private으로 선언한다. 멤버변수의 값을 초기화하거나 얻어와야할 때에는 getter, setter 혹은 생성자를 통해 접근한다.
3. 멤버함수
void accelerate() {
speed += 10;
cout << brand << " is accelerating. Speed: " << speed << " km/h" << endl;
}
void brake() {
speed -= 10;
cout << brand << " is braking. Speed: " << speed << " km/h" << endl;
}
void displayInfo() {
cout << "Car Brand: " << brand << ", Speed: " << speed << " km/h" << endl;
}
멤버함수는 객체의 동작을 정의한다. 멤버 변수를 조작하거나 객체의 기능을 수행한다.
public으로 선언하여 객체의 행동은 접근할 수 있도록 한다.
4. 생성자
int main() {
Car myCar("Toyota", 50); // 객체 myCar 생성
return 0;
}
생성자는 객체가 생성될 때 한 번만 호출되고, 멤버변수를 초기화할 때 사용한다.
생성자를 호출하게되면 brand는 Toyota, speed는 50으로 입력이 된다. 멤버변수에 직접적으로 접근하지 않고 데이터를 초기화할 수 있다는 이점이 있다.
5. Getter, Setter
void setBrand(string brand){
this->brand = brand;
}
void setSpeed(int speed){
this->speed = speed;
}
string getBrand() { return brand; }
int getSpeed() { return speed; }
Getter는 멤버변수의 값을 가져올 때 사용하고, Setter는 멤버변수의 값을 설정할 때 사용한다.
Getter와 Setter는 예외처리나 추가 기능을 구현할 때 효율적이다. 예를 들어, speed 값을 설정할 때 음수인 경우 오류를 출력하고 싶다면 Setter에 예외처리를 구현하면 된다. Setter가 없다면 speed 값을 설정할 때마다 개별적으로 예외처리를 해야 하므로, Setter를 사용하는 것이 더 효율적이다.
Getter도 마찬가지로 유용하게 활용할 수 있다. 예를 들어, speed 값을 반환할 때 "km" 단위를 자동으로 붙여서 반환하도록 할 수 있다. Getter가 없다면 speed 값을 출력할 때마다 직접 "km"를 붙여야 할 것이다.
느낀 점
코드를 작성할 때 재사용성과 확장성을 고려하는 것이 중요하다. 그러나 나는 이전까지 이를 충분히 고려하지 않고 코드를 작성해왔다. 예를 들어, 과거에 Fade Out 기능을 구현할 때, 시간에 대한 변수를 고려하지 않고 고정된 2초로 설정한 적이 있었다. 이후 기획 변경으로 4초로 수정해야 했는데, 다행히 코드 전체를 수정할 필요 없이 숫자만 변경하여 해결할 수 있었다.
그러나 문제는 그다음이었다. 단일 Sprite 이미지에만 적용되던 Fade Out 기능이 팝업 이미지나 대사와 같은 Text, Image 요소에도 필요해졌다. 이를 해결하기 위해 Text용 Fade Out, Image용 Fade Out을 각각 구현하면서 총 3개의 Fade Out 함수가 생겼다. 이로 인해 Fade Out 기능에 변경 사항이 생길 때마다 모든 함수를 수정해야 하는 비효율적인 상황이 발생했다. 이는 확장성과 재사용성을 고려하지 않은 나의 책임이었다.
최근 C++의 클래스 개념을 공부하면서, 확장성과 재사용성을 고려한 코드가 유지보수 시간을 얼마나 단축시킬 수 있는지를 다시 한번 깨닫게 되었다. 이 경험을 통해 과거의 잘못된 습관을 교정하고, 더 나은 코드를 작성할 필요성을 절실히 느끼게 되었다.
'C++ > 문법 정리' 카테고리의 다른 글
[C++] 객체지향 프로그래밍의 개념 (1) | 2025.01.02 |
---|---|
[C++] Template의 사용법 (0) | 2024.12.30 |
[C++] Dangling Pointer 대신 Smart Pointer 로 (1) | 2024.12.30 |
[C++] 오버로딩 vs 오버라이딩 (1) | 2024.12.27 |
[C++] 참조와 포인터의 차이 (1) | 2024.12.23 |