티스토리 뷰

정적변수

전역변수와 지역변수의 성격을 동시에 가지는 기억부류

 

함수 내부에서 선언하면 지역변수처럼 함수 내부에서만 접근가능하다.

함수 바깥에서 선언한 static 변수는 해당 파일 안에서만 접근가능하다.

저장장소는 전역변수가 저장되는 데이터영역.

별도로 초기화 하지 않아도 0으로 초기화되며 프로그램 실행 시 단 한번만 초기화된다.

정적 데이터 영역에 저장되므로 프로그램 실행중 항상 존재한다.

 

정적변수를 선언할 때에는 static 예약어를 자료형 앞에 반드시 기술해야 한다.

 

#include<stdio.h>
 
int TestFunction()
{
   static int test = 5;  
   //=>TestFunction()함수가 제일처음 실행될 때 단 한번만 초기화된다.
   //(두번째 호출되면 초기화되는 줄은 실행되지않음)
   ++test;
   return test;
}
 
void main()
{
   printf("1번호출: %d",TestFunction());  //=> 6
   printf("2번호출: %d",TestFunction());  //=> 7

   printf("3번호출: %d",TestFunction());  //=> 8


   //함수가 끝나도 메모리는 사라지지 않으므로 전역변수처럼 값이 그대로
존재

}
cs

최후 실행결과를 함수 스스로가 보유하도록 하고싶을 때 사용할 수있다.

전역변수는 프로그램의 소스 어떤 곳에서도 접근가능하며 그 값을 변경시킬 수 있기 때문에 전역변수를 사용하는 함수를 작성할 때 값을 예측하기가 힘들어진다. 이는 코드를 복잡하게 만들고 실행중에 잡아내기 힘든 버그를 만드는 주요 원인이 된다. 이럴 때 전역변수 대신 static 변수를 사용할 수 있다.

통용범위가 함수 내부로 국한되므로 외부참조가 어렵기 때문에 함수를 다른 프로젝트로 가져가 쉽게 재사용할 수도 있다.

이처럼 함수 내부에서 선언된 정적변수를 내부 정적변수라고 하며 정적변수 특성상 특정함수 전용으로 선언하는 경우가 많기 때문에 보통 정적변수라고 하면 내부 정적변수를 가리킨다.

함수 바깥쪽에 선언된 변수를 외부 정적변수라고 하는데 특성상 함수에 소속되어 있지 않기 때문에 전역변수와 같은 성질을 가지며 다른 점은 선언된 파일 안에서만 접근이 가능하다는 점이다. (선언된 파일 외부에서는 extern 예약어를 사용해도 참조할 수 없다.) 주로 파일의 재활용성을 높이기 위해 사용된다.

 

 

클래스 정적멤버변수

 클래스의 바깥에 선언되어 있지만 클래스 소속이다.

객체별로 할당되지 않고 모든 객체가 공유하는 멤버이다.

개별 객체와 직접적인 상관이 없고 객체 전체를 대표하는 클래스와 관련된 정보를 저장하는 특수한 멤버이다.

(전역변수나 함수와 같은 존재를 클래스 소속으로 묶은 것이다)

객체 선언 없이 직접호출가능

this 포인터 사용불가

정적 멤버변수는 선언과 정의를 반드시 분리해야한다.

자료형 앞에 static 예약어를 기술하면 된다.

 

클래스를 독립적인 하나의 부품으로 만들기 위해서는 자신의 정보를 모두 캡슐화 해야한다. 그렇지 않고 클래스와 관련된 내용을 전역변수로 선언하게 된다면 재사용하고자 할 때 전역변수와 함께 배포해야 하는 번거로움이 생기며 정보를 은폐할 수 없는 등 전역변수가 가지는 문제를 그대로 가지게 된다. 이는 객체지향적일 수 없다.

하지만 기억해야 할 것은 단지 클래스의 멤버로 들어가있기 때문에 어디까지나 논리적으로 소속된다 하는 것 뿐이지 사실상 전역변수나 함수와 같다는 것이다. 하나의 함수에서 바꾼 전역변수의 값이 그 전역변수를 쓰는 다른 함수에도 영향을 미치는 것 처럼 하나의 객체에서 바꾼 정적 멤버변수의 값은 다른 객체에도 영향을 미친다. 따라서 주의해야 한다.

정적멤버의 액세스 지정은 일반 멤버와 똑같이 적용된다.  private 영역에서 선언된 정적 멤버변수는 클래스에 속한 멤버함수로만 정적 멤버를 받아 값을 변경할 수 있다. 외부에서도 정적멤버변수를 받고싶으면 public 영역에서 선언해야 한다. 클래스 소속이기 때문에 클래스에 속한 멤버함수들은 이름만드로 정적 멤버변수를 참조할 수 있다.

 

class Count
{
private:
     int Value;
    static int Num;
   
//정적멤버변수
public:
     Count() { Num++; } 
     ~Count() { Num--; }
     void OutNum() {
          printf("현재 객체 개수 = %d\n",Num);
     }
};
 
int Count::Num=0

//외부에서 별도로 초기화 해주는작업 필요 

 

cs

 

 

클래스 내부에서 선언하는 것은 해당 변수가 해당 클래스 멤버이며 어떤 자료형을 갖는다는 것을 명시해 주는 것이지 메모리가 할당되는것은 아니다(내부 선언)

따라서 외부에서 ::연산자를 이용해 클래스 소속을 밝히고 초기값을 주어야 한다.(외부 정의)

(관습적으로 클래스를 헤더파일에 선언하고 멤버함수를 구현 파일에 작성할 때 정적멤버에 대한 외부 정의는 통상 클래스 구현 파일에 작성한다.)

 외부에서 정적 멤버변수에 접근할 때

1. 클래스::정적멤버변수;

2.클래스 객체;

객체.정적멤버변수

두 방법 모두 정적 멤버변수에 접근이 가능하지만

논리적으로 정적멤버는 객체와 직접적인 연관이 없기 때문에 2번처럼 소속으로 액세스 하는것이 바람직하지 않다.

결국 컴파일러는 객체가 소속된 클래스의 정보만 사용한다. 따라서 1번처럼 소속을 밝히고 멤버변수를 사용하면 된다.

 

클래스 정적멤버함수

private 으로 선언된 정적 멤버변수에 접근하기 위해 필요한 함수

정적 멤버함수의 본체는 클래스 선언부에 작성할 수도 있고 외부에 따로 정의할 수도 있다.

static 멤버변수와 마찬가지로 객체와 직접적으로 연관되기 보다는 클래스와 연관되며 객체를 하나도 생성하지 않아도 호출가능하다.

 클래스::정적멤버함수;

형식으로 호출하면된다.

정적멤버함수는 특정 객체에 의해 호출되는 것이 아니므로 숨겨진 인수 this가 전달되지 않는다.

따라서 정적멤버함수는 정적멤버에만 접근가능하며 일반멤버는 참조할 수 없다. 전달하길 원하는 변수는 파라미터로 넣어주어야 한다.

 

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

[macro] assert  (0) 2017.08.03
읽고 싶지 않은 문자가 있을 때  (0) 2017.06.23
[function] rand()/ rand_s() 난수생성, 난수 , 랜덤  (0) 2017.06.20
클래스 안의 클래스 접근  (0) 2017.06.11
예약어  (0) 2017.06.10
댓글