클래스(Class) (2) - 정적 멤버
정적 멤버
정적 멤버 : 틀에 해당하는 멤버(붕어빵 틀)
동적 멤버 : 객체에 포함되는 멤버. 붕어빵마다 팥의 양이 조금씩 다른 것이 해당
ex) RGB 색상 정보를 저장하는 클래스
#include <iostream> using namespace std; // 0~1 float R G B class Color { public: Color() : r(0), g(0), b(0) {} Color(float r, float g, float b) : r(r), g(g), b(b) {} float GetR() { return r; } float GetG() { return g; } float GetB() { return b; } private: float r; float g; float b; };
Color MixColors(Color a, Color b) { // 컬러랑 밀접한 관계라서 컬러 멤버에 함수를 넣고 싶음.
return Color((a.GetR() + b.GetR()) / 2, (a.GetG() + b.GetG()) / 2, (a.GetR() + b.GetR()) / 2);
}
int main() {
Color blue(0, 0, 1);
Color red(1, 0, 0);
Color purple = MixColors(blue, red);
cout << "r = " << purple.GetR() << " g = " << purple.GetG() << " b = " << purple.GetB() << '\n';
}
```
MixColors 함수가 컬러랑 밀접한 관계라서 컬러 멤버에 함수를 넣고 싶음.
- 정적 메소드를 사용해 보자
#include <iostream> using namespace std; // 0~1 float R G B class Color { public: Color() : r(0), g(0), b(0) {} Color(float r, float g, float b) : r(r), g(g), b(b) {} float GetR() { return r; } float GetG() { return g; } float GetB() { return b; } static Color MixColors(Color a, Color b) { return Color((a.r + b.r) / 2, (a.g + b.g) / 2, (a.b + b.b) / 2); } private: float r; float g; float b; }; int main() { Color blue(0, 0, 1); Color red(1, 0, 0); Color purple = Color::MixColors(blue, red); // 매개변수가 Color 타입이기 때문에 정적 메소드로 선언할 시 접근 용이. cout << "r = " << purple.GetR() << " g = " << purple.GetG() << " b = " << purple.GetB() << '\n'; }
정적 메소드 : 전역 함수가 클래스와 밀접한 관련이 있고, 멤버 변수(private field)에 접근해야 하는 경우에 사용
객체와 독립적이어서 객체의 생성과 무관함
멤버 변수의 경우 객체가 생성되어야 메모리에서 할당되기 때문에 정적 메소드 내에서는 멤버 변수를 사용할 수 없다
미리 전역에서 메모리에 할당되는 정적 멤버 변수는 정적 메소드 내에서 사용할 수 있다
위 RGB 클래스에서 생성된 객체의 수(or 일련번호)를 나타내기 위해 생성자에서 객체가 생성될 때 마다 idcounter라는 변수를 1씩 증가시켜준다고 해보자
방법 1) 전역으로 idcounter를 선언
int idcounter = 1; // 전역 // 방법 1 class Color { private: Color() : r(0), g(0), b(0), id(idcounter++) {} Color(float r, float g, float b) : r(r), g(g), b(b), id(idcounter++) {} float GetR() { return r; } float GetG() { return g; } float GetB() { return b; } int GetID() { return id; } float r; float g; float b; int id; // 추가 };
idcounter는 Color와 밀접한 관련이 있기 때문에, Color 안에 포함시키고 싶다
idcounter를 전역으로 사용하게 되면 다른 클래스를 만들 경우 idcounter를 사용하기에 애매하기 때문에 Color 클래스 안에 포함시키는게 좋다
--> 정적 멤버로 idcounter를 선언하자
#include <iostream>
using namespace std;
// 0~1 float R G B
class Color {
public:
Color() : r(0), g(0), b(0), id(idcounter++) {}
Color(float r, float g, float b) : r(r), g(g), b(b), id(idcounter++) {}
float GetR() { return r; }
float GetG() { return g; }
float GetB() { return b; }
int GetID() { return id; }
static Color MixColors(Color a, Color b) {
return Color((a.r + b.r) / 2, (a.g + b.g) / 2, (a.b + b.b) / 2);
}
static int idcounter; // 만약 idcounter가 전역으로 선언되었다 치면, color의 idcounter, item의 idcounter등등이 있어서 불편해짐.
// 최대한 정적으로 선언해서 class 안으로 집어넣자.
// static int idcounter = 1;은 불가능 (객체가 생성될 때마다 1로 대입되니까)
private:
float r;
float g;
float b;
int id;
};
int Color::idcounter = 1;
// 예를 들어 item의 idcounter가 있다면
// int Item::idcounter = 1;을 따로 선언해서 변수끼리 헷갈림을 방지할 수 있다.
// class 밖에서 값을 대입해야 하는 이유는 객체가 생성될 때 마다 idcounter에 1을 대입하면 안되기 때문
int main() {
Color blue(0, 0, 1);
Color red(1, 0, 0);
// Color purple = MixColors(blue, red);
Color purple = Color::MixColors(blue, red);
cout << "r = " << purple.GetR() << " g = " << purple.GetG() << " b = " << purple.GetB() << '\n';
cout << "Id of blue : " << blue.GetID() << '\n';
cout << "Id of red : " << red.GetID() << '\n';
cout << "Id of purple : " << purple.GetID() << '\n';
}
- 주의할 점 : 정적 멤버 변수는 class 안에서 초기화 할 수 없다.(객체가 생성될 때 마다 해당 값을 대입하면 안되기 때문)
참조) 두들낙서 C/C++ 강좌
최종 수정 : 24/02/04
'Programming Language > C++' 카테고리의 다른 글
[C++] 멤버 메서드의 활용 (0) | 2024.02.04 |
---|---|
[C++] 상수형 매개변수와 상수형 메서드 (0) | 2024.02.04 |
[C++] 클래스(Class) (1) (0) | 2024.01.30 |
[C++] 네임스페이스(namespace) (0) | 2024.01.30 |
[C++] C++ 스타일 함수 (0) | 2024.01.29 |