C언어에서의 static
- 전역변수에 선언된 static의 의미
: 선언된 파일 내에서만 참조를 허용
- 함수 내에서 선언된 static의 의미
: 한번만 초기화되고, 지역변수와 달리 함수를 빠져나가도 소멸되지 않는다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #include <iostream> using namespace std; void Counter() { static int cnt; cnt++; cout<<"Current cnt: "<<cnt<<endl; } int main(void) { for(int i=0; i<10; i++) Counter(); return 0; } | cs |
[출력결과]
Current cnt : 1
Current cnt : 2
Current cnt : 3
Current cnt : 4
Current cnt : 5
Current cnt : 6
Current cnt : 7
Current cnt : 8
Current cnt : 9
Current cnt : 10
-> static 변수는 전역변수와 마찬가지로 초기화하지 않으면 0으로 초기화, 초기화는 딱 한번만 실행된다.
즉, cnt는 Counter함수가 호출될때마다 새롭게 할당되는 지역변수가 아니다.
static 멤버변수(클래스변수)
- static 멤버변수는 '클래스 변수'라고도 한다. 일반적인 멤버변수와 달리 클래스당 하나씩만 생성되기 때문이다.
1 2 3 4 5 6 7 8 9 10 11 12 13 | class SoSimple { private: static int simObjCnt; // static 멤버변수, 클래스 변수 public: SoSimple() { simObjCnt++; cout<<simObjCnt<<"번째 SoSimple 객체"<<endl; } }; int SoSimple::simObjCnt=0; //static 멤버변수의 초기화\ | cs |
-> 위의 코드에 선언된 static 변수 simObjCnt는 SoSimple객체가 생성될 때마다 함께 생성되어 객체별로 유지되는 변수가 아니다.
객체를 생성하건 생성하지 않건, 메모리 공간에 딱 하나만 할당되어 공유되는 변수이다.
1 2 3 4 5 6 7 | int main(void) { SoSimple sim1; SoSimple sim2; SoSimple sim3; .... } | cs |
다음과 같이 sim1, sim2, sim3 객체가 static 변수 simObjCnt를 공유하는 구조가 된다.
- sim1, sim2, sim3 객체의 멤버함수에서는 simObjCnt에 멤버변수에 접근하듯이 접근이 가능하다.
하지만 simObjCnt가 객체 내에 존재하는 것은 아니다. 이 변수는 객체 외부에 있다. 다만 객체에 멤버변수처럼 접근할 수 있는 권한을 준 것이다.
- 생성 및 소멸의 시점도 전역변수와 동일하다.
* simObjCnt를 별도로 초기화하고 있는 이유?
- 만약 static변수를 생성자에서 초기화하면, 객체가 생성될때마다 변수 simObjCnt는 0으로 초기화되기 때문
* static 멤버변수 접근방법
simObjCnt를 public으로 선언하면 클래스의 이름, 객체의 이름을 통해 어디서든 접근이 가능하다.
1 2 3 4 5 6 7 8 9 | int main(void) { SoSimple sim1; SoSimple sim2; cout<<sim1.simObjcnt<<endl; cout<<sim2.simObjcnt<<endl; cout<<SoSimple::simObjCnt<<endl; } | cs |
-> 위의 출력하는 세문장은 동일한 출력을 한다.
그중 sim1, sim2의 출력은 멤버변수에 접근하는 것과 같은 오해를 일을킨다.
따라서 public static멤버에 접근할 땐, SoSimple::simObjCnt와 같이 클래스의 이름을 이용하여 접근하는 것이 좋다.
static 멤버함수
static 멤버함수 역시 그 특성이 static 멤버변수와 동일하다. 따라서 위에서 설명한 특성이 그대로 적용된다.
- 선언된 클래스의 모든 객체가 공유
- public으로 선언이 되면, 클래스의 이름을 이용해서 호출이 가능
- 객체의 멤버로 존재하는 것이 아니다.
*static멤버함수는 객체의 멤버로 존재하지 않기 때문에 다음의 코드는 컴파일 에러가 발생
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | class SoSimple { private: int num1; static int num2; public: SoSimple(int n): num1(n) {} static void Adder(int n) { num1+=n; // 컴파일 에러발생 num2+=n; } }; int SoSimple::num2 = 0; | cs |
-> 객체의 멤버가 아니기 때문에 멤버변수에 접근이 불가
-> 객체 생성 이전에도 호출이 가능하다. 객체 생성 이전에 멤버변수에 접근하는 것은 불가
* static 멤버함수 내에서는 static 멤버변수와 static멤버함수만 호출이 가능
const static 멤버
클래스에 선언된 const 멤버변수(상수)의 초기화는 이니셜라이저를 통해야만 했다. 그러나 const static으로 선언된 멤버변수(상수)는 선언과 동시에 초기화가 가능하다.
1 2 3 4 5 6 7 8 | class CountryArea { public: const static int RUSSIA = 1707540; const static int CANADA = 998467; const static int CHINA = 957290; const static int SOUTH_KOREA = 9922; }; | cs |
[참고자료]
윤성우 열혈 C++ 프로그래밍 06-3 C++에서의 static
'Software Development > C, C++' 카테고리의 다른 글
[C++] 오버라이딩과 가상함수 (0) | 2019.01.01 |
---|---|
[C++] 상속(Inheritance) (0) | 2018.12.31 |
[C++] const, friend 키워드 (0) | 2018.12.30 |
[C++] 복사 생성자의 호출시점 (1) | 2018.12.29 |
[C++] 복사생성자의 깊은복사 & 얕은복사 (0) | 2018.12.29 |