2015. 2. 3.

[C++]static

 static는 프로그래밍 언어를 배우다보면 자연스럽게 접하게 되는 키워드 중 하나이다. 어렴풋이 static으로 변수를 선언하면 전역변수처럼 사용할 수 있다고 하더라 정도의 지식을 이미 가지고 있는 사람도 있을 것이다. 그런데 C에서의 static과 C++에서의 static은 사용이 조금 다르다.C++에는 클래스가 존재하고, 멤버변수로 static 변수를 지닐 수 있기 때문이다. 이런 차이를 살펴보고 static에 대해서 깔끔하게 정리하고 넘어가자.


C에서 static의 의미

  • 전역변수에 선언된 static: 선언된 파일 내에서만 참조하라는 의미
  • 함수 내 선언된 static: 한 번만 초기화되고, 함수를 빠져나가도 소멸되지 않음
 함수 내 선언된 static 변수가 어떻게 사용되는지 보여주는 코드이다. static 변수는 전역변수와 마찬가지로 초기화하지 않으면 0으로 초기화된다. 그리고 초기화는 딱 한 번 이루어진다.



static 멤버 변수

 클래스에 선언된 static멤버 변수를 의미한다. 클래스에 선언된 static 멤버변수는 함수 내 선언된 static 변수와 마찬가지로 하나만 존재한다. 클래스의 객체가 여러 개 생성되더라도 static 멤버변수는 하나이다.

 친절한 그림으로 살펴보자.


 먼저 보통의 멤버 변수를 가지는 클래스의 경우이다. 객체가 생성되고 각각의 객체가 독립적으로 멤버변수 a, b를 가진다.


 static 멤버변수를 가지는 클래스의 경우이다. 객체가 생성되고 static 멤버변수는 하나만 생성된다. 그리고 각각의 객체는 하나의 static 변수를 공유한다.

 그렇다면 static 멤버변수는 어떤 객체 소유인가? static 멤버변수는 어떤 객체에도 속해있지 않다. 심지어 static 멤버변수는 객체를 생성하지 않아도 접근하여 사용할 수 있다. static 변수는 전역변수와 마찬가지로 main() 함수가 실행되기 전에 생성된다.

 위의 코드는 static 멤버변수의 예시와 static 멤버변수 초기화 방법까지 보여주고 있다. static 멤버변수 초기화가 클래스 외부에 있는 것도 이상하고, static 멤버변수 초기화는 조금은 어색하게 느껴질지도 모른다. 하지만 static의 특성을 살펴보면 조금 이해할 수 있다. 먼저 보통의 멤버변수를 초기화하듯이 생성자에서 static 변수를 초기화하면 객체를 생성할 때마다 static 멤버변수는 반복적으로 초기화될 것이다. 그래서 static 멤버변수를 위한 초기화 문법이 별도로 정의되어 있다. 엄청난 문법적인 이유가 있어서 저런 형태로 초기화하는 것이 아니라는 점만 알아두자. 즉 static 멤버변수를 초기화하는 문법적인 방법이다.

 위의 코드에서는 static 멤버변수를 private으로 선언하였다. 그래서 해당 객체들만 접근할 수 있다. 해당 객체들만 접근할 수 있다고 말하면 또다시 static 멤버변수는 객체에 속해있다고 착각할 수 있다. 그렇게 생각해서는 안된다. 객체들은 static 멤버변수에 접근할 수 있는 권한을 가지고 있는 것이지 static 멤버변수를 가지고 있는 것은 아니다. 다시 돌아가서 static 멤버변수를 public으로 선언하면 어떻게 되겠는가? 그러면 클래스의 namespace 혹은 객체의 이름, 참조자, 포인터 등으로 자유롭게 접근할 수 있지 않을까? 이를 다시 생각해보면 public으로 선언된 static 변수는 전역변수와 비슷한 효과를 낼 수 있다 여겨진다.

 위에서 볼 수 있듯이 public으로 선언된 static 멤버변수는 객체를 생성하지 않고도 접근해서 사용할 수 있다. 클래스의 namespace을 통해서도 접근할 수 있다. 이 정도면 전역변수처럼 충분히 사용할 수 있을 것 같다.


static 멤버함수

 static 멤버함수의 특성은 static 멤버변수와 동일하다. 고민없이 받아들이면 된다.

  • 선언된 클래스의 모든 객체가 공유한다.
  • public으로 선언되면 namespace를 사용하여 호출할 수 있다.
  • 객체의 멤버로 속하지 않는다.
 static 멤버변수와 정말 다른 것이 없다. 주의할 점만 짚고 넘어가자.

 static으로 선언하면 멤버변수든 멤버함수든 객체를 생성하지 않아도 먼저 메모리에 할당된다. 만약 위의 클래스의 static 멤버함수인 Adder() 함수를 객체를 생성하지 않은 상태에서 호출하면 어떻게 될까? static 멤버변수인 num2는 메모리에 존재하지만 num1은 아직 메모리에 존재하지 않는 상태이다. 그런데 Adder() 함수를 호출하면 메모리에 존재하지 않는 num1을 참조하게 되므로 에러를 발생시킨다. 그래서 컴파일 에러가 발생한다. 그러므로 static 멤버함수는 static 멤버변수, static 멤버함수만 호출하도록 제한한다.


정리하면
 static 멤버변수와 static 멤버함수는 객체와 독립적으로 존재한다.
 static 멤버변수와 static 멤버함수를 public으로 선언하면 전역변수처럼 사용할 수 있다.

댓글 없음:

댓글 쓰기