static 변수에 접근하는 법
1. static 변수가 정의된 클래스 내에서는 static 변수의 이름만으로 접근이 가능하다.
2. class명::static변수명++;<<이런식으로 어디서든지 접근 가능하다. (class 내에 public으로 선언이 되었을 경우)
3. 객체명.static변수명(비추천)
C언어에서의 static
- 전역변수에 선언된 static의 의미
- => 선언된 파일 내에서만 참조를 허용하겠다는 의미
- 함수 내에 선언된 static의 의미
- => 한번만 초기화되고, 지역변수와 달리 함수를 빠져나가도 소멸되지 않는다.
#include <iostream>
using namespace std;
void Counter() {
static int cnt;
//전역변수와 마찬가지로 초기화하지 않으면 0으로 초기화된다.
//딱 한번만 실행이 된다.
cnt++;
cout << "Current cnt: " << cnt << endl;
}
int main(void) {
for (int i = 0; i < 10; i++)
Counter();
return 0;
}
static 멤버변수(클래스 변수)
#include <iostream>
using namespace std;
class SoSimple {
private:
static int simObjCnt;//SoSimple 객체에 의해서 공유된다.
public:
SoSimple() {
//SoSimple의 멤버함수(생성자)내에서는 마치 멤버변수인 것처럼 접근이 가능하다.
simObjCnt++;
cout << simObjCnt << "번째 SoSimple 객체" << endl;
}
};
int SoSimple::simObjCnt = 0;//static변수는 클래스 외부에서 초기화해야 한다.
class SoComplex {
private:
static int cmxObjCnt;
public:
SoComplex() {
cmxObjCnt++;
cout << cmxObjCnt << "번째 SoComplex 객체" << endl;
}
SoComplex(SoComplex& copy) {
cmxObjCnt++;
cout << cmxObjCnt << "번째 SoComplex 객체" << endl;
}
};
int SoComplex::cmxObjCnt = 0;
int main(void) {
SoSimple sim1;
SoSimple sim2;
SoComplex cmx1;
SoComplex cmx2 = cmx1;
SoComplex();
return 0;
}
static 멤버변수는 '클래스 변수'라고도 한다.
일반적인 멤버변수와 달리 클래스당 하나씩만 생성되기 때문이다.
SoSimple 클래스 안에 선언된 static 변수는 모든 SoSimple객체가 공유하는 구조이다.
생성 및 소멸의 시점도 전역변수와 동일하다.
위의 코드에 선언된 static변수 simObjCnt는 SoSimple객체가 생성될 때마다 함께 생성되어 객체별로 유지되는 변수가 아니라,
객체를 생성하든 말든 메모리 공간에 딱 하나만 할당이 되어서 공유되는 변수이다.
sim1.sim2객체가 static변수 simObjCnt를 공유하는 구조가 된다.
sim1,sim2 객체의 멤버함수(생성자)에서는 simObjCnt에 멤버변수에 접근하듯이 접근이 가능하다.
하지만 SimObjCnt가 객체 내에 존재하는것이 아니라, 외부에 있지만 객체에게 멤버변수처럼 접근할 수 있는 권한을 줬을 뿐이다.
static 변수를 생성자에서 초기화하면 안되는 이유
SoSimple(){
simObjCnt = 0;
simObjCn++;
cout<<simObjCnt<<"번째 SoSimple 객체"<<endl;
}
SoSimple의 생성자를 위와 같이 정의한다면,
객체가 생성될 때마다 변수 simObjCnt는 0으로 초기화된다.
변수 simObjCnt는 객체가 생성될 때 동시에 생성되는 변수가 아니라,
이미 메모리 공간에 할당이 이뤄진 변수이기 때문이다.
int SoSimple::simObjCnt = 0;
따라서 static 멤버변수의 초기화 문법은 위와 같이 별도로 정의되어야 한다.
이는 클래스의 static 멤버 변수 simObjCnt가 메모리 공간에 저장될 때
0으로 초기화 하라는 뜻이다.
static 멤버변수의 public 선언
static 멤버가 public으로 선언되면, 클래스의 이름 또는 객체의 이름을 통해서 어디서든 접근이 가능하다.
#include <iostream>
using namespace std;
class SoSimple {
public://static 멤버변수가 public으로 선언되었다.
static int simObjCnt;
public:
SoSimple() {
simObjCnt++;
}
};
int SoSimple::simObjCnt = 0;
int main(void) {
cout << SoSimple::simObjCnt << "번째 SoSimple 객체" << endl;
//SoSimple 객체가 하나도 생성하지 않은 상태이지만,
//클래스의 이름을 이용해서 simObjCnt에 접근하고 있다.
SoSimple sim1;
SoSimple sim2;
cout << SoSimple::simObjCnt << "번째 SoSimple 객체" << endl;
cout << sim1.simObjCnt << "번째 SoSimple 객체" << endl;
cout << sim2.simObjCnt << "번째 SoSimple 객체" << endl;
return 0;
}
static 멤버함수
- 선언된 클래스의 모든 객체가 공유한다.
- public으로 선언되면, 클래스의 이름을 이용해서 호출이 가능하다.
- 객체의 멤버로 존재하는 것이 아니다.
static 멤버함수 내에서는 static 멤버변수와 static 멤버함수만 호출이 가능하다.
static함수는 객체 내에 존재하는 함수가 아니기 때문에 멤버변수나 멤버함수에 접근이 불가능하다.
const static 멤버
클래스 내에 선언된 const 멤버변수(상수)의 초기화는 이니셜라이저를 통해야만 한다.
그러나 const static으로 선언되는 멤버변수(상수)는 다음과 같이 선언과 동시에 초기화가 가능하다.
#include <iostream>
using namespace std;
class CountryArea {
public:
const static int RUSSIA = 1707540;
const static int CANADA = 998567;
const static int CHINA = 957290;
const static int SOUTH_KOREA = 9922;
};
int main(void) {
cout << "러시아 면적: " << CountryArea::RUSSIA << "km" << endl;
cout << "캐나다 면적: " << CountryArea::CANADA << "km" << endl;
cout << "중국 면적: " << CountryArea::CHINA << "km" << endl;
cout << "한국 면적: " << CountryArea::SOUTH_KOREA << "km" << endl;
return 0;
}
const static 멤버변수는 클래스가 정의될 때 지정된 값이 유지되는 상수이기 때문에,
위 코드에서처럼 초기화가 가능하도록 문법으로 정의하고 있다.
키워드 mutable
mutable은 const 함수 내에서의 값의 변경을 예외적으로 허용한다.
mutable은 제한적으로, 매우 예외적인 경우에 한해서 사용하는 키워드이다.
#include <iostream>
using namespace std;
class SoSimple {
private:
int num1;
mutable int num2;//const 함수에 대해 예외를 둔다.
public:
SoSimple(int n1, int n2) :num1(n1), num2(n2)
{ }
void ShowSimpleData() const {
cout << num1 << ", " << num2 << endl;
}
void CopyToNum2() const {
num2 = num1;//const 함수 내에서 num2에 저장된 값을 변경하고 있다.
}
};
int main(void)
{
SoSimple sm(1, 2);
sm.ShowSimpleData();
sm.CopyToNum2();
sm.ShowSimpleData();
return 0;
}
'공부 > C++' 카테고리의 다른 글
[C++] 7-2. 상속의 문법적인 이해 (0) | 2024.11.06 |
---|---|
[C++] 7-1. 상속에 들어가기에 앞서 (0) | 2024.11.06 |
[C++] 6-2. 클래스와 함수에 대한 friend 선언 (0) | 2024.10.31 |
[C++] 6-1. const 보충 (0) | 2024.10.31 |
[C++] 5-3. 복사생성자의 호출 시점 (0) | 2024.10.31 |