최신목록

2016년 1월 20일 수요일

[C++]static 멤버 변수와 함수

C에서는 특정함수 안에서 static 변수를 선언하여  특정 함수 안에서만 전역변수처럼 사용한다.

C++에서는 객체지향이기때문에 전역변수를 사용할 것을 권하지 않는다. 때문에 전역변수를 대체할 수 있는 클래스 멤버 변수, 클래스 멤버 함수 라는 static 멤버 변수, 함수가 생기게 되었다. 전역변수처럼 클래스와 독립적인 곳에 존재하게 되면 모든 클래스에서 접근이 가능하다. private 이냐, public이냐에 따라 접근 범위에 제한을 둘 수 있다. staic 멤버 함수는 클래스와 독립공간에서 모든 클래스가 공유하여야 하므로 내부에서 사용하는 변수 또한 static 멤버 변수만을 사용하여야 하고 일반 멤버 변수를 사용해서는 안된다.

1. static 멤버 변수

static 멤버 변수는 보통 클래스의 데이터 멤버를 const로 선언하였을때 이 값은 변경되지 않는 상수값이기 때문에 어차피 클래스 객체간에 모두 동일하게 사용되어 메모리방지를 막기 위해 static으로 선언하여 사용하는 경우가 많다. 아래는 const 변수가 아닌 일반 변수를 얘를 들었다.

class test
{
        int a;
public:
        static int c;
public:
        test() {a = 10; c++;}
};
int test::c = 10;  //-->static 멤버 변수 초기화
int _tmain(int argc, _TCHAR* argv[]) { test t1; test t2; return 0; }
위에서처럼 static 멤버 변수는 초기화를 클래스 외부에서 해주어야 하면 초기화를 안하면 컴파일시 아래와 같은 외부 기호를 확인할 수 없다는 에러 메시지가 난다. 문법처럼 기억해두면 될듯.
c++11 이상부터 static 멤버 변수 선언시 초기화가 가능하다. 이는 컴파일러 버전에 영향을 받으므로 Visual Studio 사용시 아래 msdn 사이트를 참고하여 확인하면 된다.

https://msdn.microsoft.com/ko-kr/library/hh567368.aspx



위의 프로그램에서 static 멤버 변수 c의 변화를 생각해보자. 10으로 초기화가 되었으며 main 함수에서 클래스 객체 생성전에 1이 증가하였고(test::c++;) test 클래스 두개를 차례대로 생성하였고 생성할때마다 c를 1씩 증가시켰으므로 t1.c 와 t2.c 는 모두 13이 되어있게된다. 이는 전역변수를 사용한 효과와 똑같은 효과라 볼 수 있다.

그러나 이 변수를 test라는 클래스 객체만이 공유 하고 싶다면 어떻게 할까? 이 때 private으로 변수를 선언하여 사용한다.
일반적으로 클래스 데이터 멤버를 public으로 선언하여 외부에 노출하는것은 바람직하지 않다. private이나 protected로 선언하여 public get/set을 통해 접근 권한을 얻도록 하는것이 좋다.

class test
{
  int a;
private:
  static int c;
public:
         test() {a = 10; c++;}
};

int test::c = 10;

int _tmain(int argc, _TCHAR* argv[])
{
         test::c++;  //--> error C2248: 'test::c' : private 멤버('test' 클래스에서 선언)에 액세스할 수 없습니다.
         test t1;
         test t2;
         return 0;
}

위처럼 private인 static 멤버 변수를 다른 영역에서 호출시 에러가 발생하며 위 프로그램은 test::c++ 을 주석처리하면 t1.c와 t2.c는 모두 12가 된다.

2. static 멤버 함수

class test
{
        int a;
        static int c;
public:
        test() {a = 10; c++;}
        void change()
        {
                c = 0;
        }
        static void change_static()
        {
                c = 20;
                a = 20;  //-->error C2597: 비정적 멤버 'test::a'에 대한 참조가 잘못되었습니다.
        }
};

위에 예제처럼 일반 멤버함수에서는 static 멤버 변수를 사용할 수 있으나 static 멤버 함수에서는 static 멤버 변수만을 사용할 수 있음을 보여준다. 이는 전역함수에서 다른 함수의 지역변수를 가져다 쓰는 것과 같은 이치라 생각하면 된다.

이처럼 static 멤버 함수는 클래스 객체의 멤버 변수들과 독립적이고 변경이 불가하다. 그러므로 static 멤버 함수의 const 지정은 무의미하다. static 멤버 함수에 const 지정시 컴파일 오류가 난다.


댓글 없음:

댓글 쓰기