C++ Chapter 8.10 : static 정적 멤버 변수
카테고리: Cpp
태그: Cpp Programming
인프런에 있는 홍정모 교수님의 홍정모의 따라 하며 배우는 C++ 강의를 듣고 정리한 필기입니다. 😀
🌜 [홍정모의 따라 하며 배우는 C++]강의 들으러 가기!
chapter 8. 객체 지향의 기초 : static 정적 멤버 변수
🔔 static 멤버 변수란?
모든 객체가 한 메모리를 공유하는 멤버 변수. 객체 별로 각각 할당되는 멤버가 아니라 모든 객체가 공유하는 멤버다.
- 모든 객체가 공유하는 멤버 변수이기 때문에
- 메모리는 프로그램 시작때부터 차지하고 있으며 메모리에 내내 값이 유지된다.
- 객체 생성 전에도 메모리 존재
- 따라서 객체 생성 전에 반드시 미리 초기화를 해주어야 한다.
- 객체와는 독립적으로 존재한다.
- 객체 생성 전에도 메모리 존재
- 객체 이름으로도 접근이 가능하지만 클래스 이름으로도 접근이 가능하다.
int Something::s_value = 1;
- s_value가
static
멤버 변수라면 객체1의 s_value 와 객체2의 &s_value 는 주소가 동일하다.
- 메모리는 프로그램 시작때부터 차지하고 있으며 메모리에 내내 값이 유지된다.
- 어떤 특정 타입의 모든 객체들의 수 라던지 모든 객체들이 알고 있고 공유할 수 있어야 하는 멤버 변수를
static
으로 쓴다.
🔔 static 멤버 변수의 정의
선언과 정의의 구분
- 이건 단순
선언
이다.- 컴파일러에게 변수의 정보만을 주며
- 실제 메모리를 사용하지는 않음
- 아래 코드는 단순히 static멤버 변수 m_value의 존재를 컴파일러에게 알려주는 것일 뿐이다.
class Something { public: static int m_value; // 선언. 메모리를 차지 하지 않는다. }
- 이건
정의
이다.- 실제 메모리가 할당된다
초기화
하는 것도 정의해주는 과정이다.- 메모리에 값을 넣으니까.
- 아래 코드는 static멤버 변수 m_value 의 메모리를 할당해주고 값을 1을 넣어주는 과정이다.
int Something::m_value = 1; // 정의. 전역 범위의 메모리를 할당 받는다.
static
멤버 변수는 모든 객체가 공유해야 하므로 프로그램 전체 영역에서 메모리 유지가 되야 한다. 따라서 반드시 전역 범위에서 정의 및 초기화를 해주어야 한다.
반드시 전역 범위에서 초기화 해야 한다.
int Something::m_value = 1;
전역 범위에서
자료형이름 클래스이름::static변수이름 = 초기화할값
형식으로 초기화 해준다.
class Something
{
public:
static int m_value = 1; // 에러 💥 여기서 초기화 불가능
}
static
멤버 변수를 저렇게 클래스 내에서 초기화 하면 객체를 생성할 때마다static
멤버 변수 값이 계속 해서 덮어 씌워질 것이다. 왜냐면 모든 객체들이 이 멤버를 공유하기 때문이다.static
멤버 변수는 클래스 내에서 선언만 가능하고 정의는 불가능
static
멤버 변수는 모든 객체들이 접근해야 하므로 프로그램 시작부터 끝까지 유지되어야 하기 때문에 전역 범위 에서만 정의(초기화)할 수 있다.
- 따라서
static
멤버 변수는 main 함수는 물론이고 생성자 안에서도 초기화 할 수 없다.- 생성자도 static여야 static 멤버 변수를 초기화시킬 수 있는데 C++에서는 static 생성자를 지원하지 않는다.
#include <iostream>
using namespace std;
class Something
{
public:
static int m_value; // 선언. .
};
int Something::m_value = 1; // 👈👈 전역 범위에서 초기화
int main()
{
// int Something::m_value = 1; 👈👈 에러!!! 전역 범위에서만 가능.
cout << Something::m_value << endl; // 1 출력 👈👈 객체 생성 전에도 사용 가능
cout << &Something::m_value << endl; // 0x601070 출력 👈👈 객체 생성 전에도 사용 가능
Something st1;
Something st2;
st1.m_value = 2;
cout << st1.m_value << endl; // 2 출력
cout << &st1.m_value << endl; // 0x601070 출력
cout << st2.m_value << endl; // 2 출력
cout << &st2.m_value << endl; // 0x601070 출력
st2.m_value = 1024;
cout << Something::m_value << endl; // 1024 출력
return 0;
}
- &st1.m_value, &st2.m_value, &Something::m_value 전부 주소가 동일하다
- 따라서 st1.m_value 값을 바꾸면 st2.m_value, Something::m_value 값들도 동시에 똑같이 바뀐다.
- 모든 객체는
static
변수의 메모리를 공유하기 때문
- int Something::m_value = 1;
- 이렇게 전역 범위에서 초기화를 반드시 해주어야 한다.
- 반드시 전역 범위내에서 정의 해주어야 하기 때문에 main 함수 내에서 int Something::m_value = 1; 해줄 수 없다.
- 이렇게 전역 범위에서 초기화를 반드시 해주어야 한다.
정의 및 초기화는 헤더 파일 내에서는 불가능하다.
헤더 파일과 .cpp 파일로 분리할 때,
static
멤버 변수는 반드시 .cpp파일에서 초기화 해준다.
- static 멤버 변수의 초기화는 헤더파일에선 불가능하다.
- 여러 곳에서 헤더 파일을 include할 때 마다 static 멤버 변수를 여러번 정의 및 초기화 하는게 될테니까
📜Something.h
class Something
{
public:
static int m_value; // 클래스 내에선 초기화 불가능
};
int Something::m_value = 1; // 💥에러!💥 헤더 파일 내에선 초기화 불가능
📜Something.cpp
int Something::m_value = 1;
🔔 static const 멤버 변수
static const int m_value;
static const
멤버 변수는 클래스 내에서 초기화 하는 것이 가능하다.
const
이므로 값을 변경하는 것이 불가능하기 때문에 그 모습 그대로를 모든 객체가 공유하기 때문에- 한번 초기화 한 이후론 값을 변경하는 것이 불가능하다.
- 이 같은 경우는 클래스 내부에서 초기화가 가능하다.
const
는 값이 컴파일 타임에 결정되기 때문에
- 따라서 헤더파일 내에서도 초기화가 가능하다.
#include <iostream>
using namespace std;
class Something
{
public:
static const int m_value; // 가능! 🙆♀️
};
// int Something::m_value = 1; 👈 const라 클래스 밖에서 기존 값 변경이 불가능
int main()
{
Something st;
st.m_value = 1024; // 👈 💥에러💥 const라서 값 변경 불가
return 0;
}
🔔 private인 static 멤버 변수 초기화
private
한 멤버 변수면 클래스 내에서만 접근이 가능하고 외부에서는 접근이 불가능하기 때문에 초기화는 어떻게 할까 의문이 들었지만, static
멤버는 클래스 내부에선 초기화가 불가능하므로 private
하더라도 클래스 외부에서 정의가 가능하다.
#include <iostream>
using namespace std;
class A
{
private: // ⭐⭐⭐
static int s_value;
};
int A::s_value = 1; // 👈 private이더라도 전역범위에서 정의 및 초기화 가능
int main()
{
A a;
cout << a.s_value << endl;
A::s_value = 1; // 👈 💥에러!💥 private이므로 s_value 에접근이 불가능하다.
return 0;
}
🔔 static 멤버 변수를 클래스 내부에서 초기화 하는 방법
inner-class
를 사용하여 클래스 안에 클래스를 하나 더 만들고 그 클래스의 생성자 안에서 초기화를 하는 방법이 있다. 이때 클래스에서 클래스의 클래스 객체를 static 멤버 변수로 선언해주어야 한다.
#include <iostream>
using namespace std;
class Something
{
public:
class _init // inner class
{
public:
_init()
{
s_value = 9876; // s_value 접근 가능.
}
};
private:
static int s_value;
static _init s_initializer;
};
// int Something::s_value = 1234;
Something::_init Something::s_initializer;
static
멤버 변수인 s_value를 Something 클래스 내에서 간접적으로 초기화 하는 방법- Something 클래스 내에 _init 클래스를 만들어준다.
- _init 클래스의 생성자에서
static
멤버 변수인 s_value를 초기화 해준다.- 이렇게 간접적으로 클래스 내부에서 초기화하게 됨.
- Something 클래스의
static
멤버 변수로 _init 타입의 s_initializer를 추가해준다. - 클래스 외부인 전역 범위에서 Something::_init Something::s_initializer; 로
static
멤버 변수인 s_initializer를 정의 해준다.- 데이터 타입은 Something::_init
🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄
댓글 남기기