C++/Class 2021. 3. 16. 00:05

정적 멤버 함수 (Static Member Function)

  • 클래스의 멤버 함수들은 한 번만 정의하고, this를 통해 인스턴스의 주소를 포함해서 전달한다고 했다.

    • 인스턴스 없이 범위 지정 연산자로 바로 멤버 함수를 사용하고자 할 때, 굳이 static을 붙여야 동작할 수 있는건가 싶어서 간단한 예제를 만들어 보았다.

      #include <iostream>
      
      class Something
      {
        static int    s_value_;
      
      public:
        int    getValue()
        {
          return s_value_;
        }
      };
      
      int Something::s_value_ = 1;
      
      int        main()
      {
        using namespace std;
      
        cout << Something::getValue();  // 에러
      }
      error C2352: 'Something::getValue': illegal call of non-static member function
      • 내부적으로 인스턴스의 주소를 인자로 전달하는 원리인데, 범위 지정 연산자로 함수를 사용할 경우 인스턴스의 주소가 없으므로 에러가 발생하는 것이다.

예제

  • static 멤버 함수에는 this 포인터가 인자로 들어가지 않는다.

    • 즉, this 포인터로 접근해야하는 모든게 안된다.

    • 정적으로 메모리에 존재하는 변수에는 접근할 수 있지만, static 변수가 아닌 일반 변수에는 접근할 수 없다.

    #include <iostream>
    
    class Something
    {
      static int    s_value_;
    
    public:
      static int    getValue()
      {
        return s_value_;
      }
    };
    
    int Something::s_value_ = 1;
    
    int        main()
    {
      using namespace std;
    
      cout << Something::getValue() << endl;
    
      Something    s1;
    
      cout << s1.getValue() << endl;
    }
    
    /* stdout
    1
    1
    */
  • 함수 포인터를 통한 이해

    • 일반 멤버 함수를 저장하는 예제

      #include <iostream>
      
      class Something
      {
        static int    s_value_;
      
      public:
        static int    getValue()
        {
          return s_value_;
        }
      
        int            temp()
        {
          return s_value_;
        }
      };
      
      int Something::s_value_ = 1;
      
      int        main()
      {
        using namespace std;
      
        Something    s1, s2;
      
        cout << s1.getValue() << endl;
      
        int    (Something:: * fptr1)() = &Something::temp;
      
        cout << (s2.*fptr1)() << endl;
      }
      
      /* stdout
      1
      1
      */
    • 정적 멤버 함수를 저장하는 예제

      #include <iostream>
      
      class Something
      {
        static int    s_value_;
      
      public:
        static int    getValue()
        {
          return s_value_;
        }
      
        int            temp()
        {
          return s_value_;
        }
      };
      
      int Something::s_value_ = 1;
      
      int        main()
      {
        using namespace std;
      
        Something    s1, s2;
      
        cout << s1.getValue() << endl;
      
        int    (Something:: * fptr2)() = &Something::getValue;  // 에러
      
        cout << (s2.*fptr2)() << endl;
      }
      error C2440: 'initializing': cannot convert from 'int (__cdecl *)(void)' to 'int (__thiscall Something::* )(void)'
      • 즉, 여기서의 Something::getValue 함수는 int (*)(void) 형태의 함수인 것을 알 수 있다.

      • fptr2의 형태를 바꾸면 작동된다.

      #include <iostream>
      
      class Something
      {
        static int    s_value_;
      
      public:
        static int    getValue()
        {
          return s_value_;
        }
      
        int            temp()
        {
          return s_value_;
        }
      };
      
      int Something::s_value_ = 1;
      
      int        main()
      {
        using namespace std;
      
        Something    s1, s2;
      
        cout << s1.getValue() << endl;
      
        int    (*fptr2)() = &Something::getValue;
      
        cout << fptr2() << endl;
      }
      /* stdout
      1
      1
      */

요약

  • static 멤버 함수는 this 포인터 인자가 들어가지 않는다.

    • 인스턴스를 특정할 수 없으므로 static 멤버 변수만 호출 가능하다.

    • 범위 지정 연산자로 정적 멤버 함수를 사용할 수 있다.

'C++ > Class' 카테고리의 다른 글

C++ 익명 객체 (Anonymous Class)  (0) 2021.03.16
C++ friend  (0) 2021.03.16
C++ 정적 멤버 변수 (Static Member Variable)  (0) 2021.03.15
C++ static (Class)  (0) 2021.03.15
C++ 체이닝(Chaining)  (0) 2021.03.15