Programming Language/C++

[C++] 클래스(Class) (2) - 정적 멤버, 정적 메서드

lumana 2024. 1. 30. 04:28

클래스(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