class에서 사용되는 static은 앞선 챕터에서 다루었던 빌드의 링크 프로세스에서 사용되는 static과는 다른 의미이다.
static의 사용 예시는 다음과 같은 3가지 경우로 나누어 볼 수 있다.
1. static member function (static 멤버 함수)
2. static member variable (static 멤버 변수)
3. static variable in a function. (함수 안의 static 변수)
1. static member function
1) static member function은 object와 연관되어 있지 않다!
이 코드에서처럼 멤버 함수는 굳이 object를 만들지 않아도 콜 할 수 있다.
멤버 함수가 굳이 객체를 만들지 않아도 콜 할 수 있는 이유는,
static member function은 object와 연관이 되어 있지 않기 때문이다.
이는 class의 this 키워드와 관련되어 있다.
this 키워드는 object의 주소를 가리키는데,
static member function은 object adrress와 binding이 안 되어 있어서 object를 생성하지 않아도 콜이 됨.
2) Static 함수에서는 member variable 호출 불가
static member function이 object를 가리킬 수가 없다면 당연히 그 member variable 또한 가리킬 수 없다.
만약 static 함수에서 class의 member variable인 mAge를 사용한다면 에러가 난다.
당연히 위에서 언급했듯이 static member function은 object와 관련되어 있지 않기 때문에 this 키워드를 통해서 member variable을 가리킬 수 없다. 따라서 이와 같이 this->mAge 는 불가능하다.
3) static function에서 member function 호출 불가능
멤버 변수와 마찬가지로 멤버 함수 또한 static 함수에서는 콜 불가능하다.
speak(); 함수 콜 하게 되면 컴파일 에러가 나는데,
멤버 함수는 this라는 object 주소를 통해서 콜 하게 되는데 (this->speak(); 이런 식)
static 함수에는 this가 들어가지 않기 때문에 콜 할 수 없는 것이다.
반면 Cat에서 kitty라는 object를 만들고 kitty에서 staticSpeak() 를 콜 할 수 있다.
2. static member variable
*static member variable은 프로그램이 시작되기 전에 초기화 시켜 주어야 한다!
static 멤버변수를 speak() 함수에서 사용하려고 하는데, 간단하게 count를 올려 주고 이 카운트를 출력해 줄 것이다.
메인 함수에서 2개의 서로 다른 오브젝트를 만들고 각각의 오브젝트에서 speak() 함수를 콜 해주었다.
실행하면 1meow 와 2meow로 결과가 출력되고 count가 ++ 된 것을 볼 수 있다.
이게 이상해 보일 수 있는데, 왜냐면 멤버 변수를 static으로 만들었을 뿐인데,
서로 다른 object인 kitty와 nabi가 static member variable을 공유하고 있다.
이를 이해하기 위해서는 프로세스의 메모리 뷰를 이해하고 있어야 한다.
그림으로 나타내 보면,
현재 이 코드는 힙 메모리 안에 static 메모리 공간까지 사용하고 있다.
static으로 만든 count 변수는 object에 들어있는 것이 아니라 static 공간 안에 할당되어 있다.
따라서 kitty, nabi 객체의 count 변수(static)는 obejct안에 귀속되어 있는 것이 아니라 static 공간 안에 할당되어 있고
모든 object에서 이 값을 공유하고 있는 것이다.
결국 kitty라는 첫 번째 object가 speak라는 함수를 사용하면서 count를 1로 올려준 것이고 두 번째로 nabi object가 speak()함수를 콜 하면서 카운트를 2로 올려준 것이다.
즉 각각의 다른 오브젝트가 스태틱 키워드를 사용해서 카운트 메모리를 공유한 것이다.
이처럼 static 변수를 public으로 선언하게 되면 중간에 cat::count = -999; 와 같이 아무데서나 접근이 가능하다.
이를 방지하기 위해서 private으로 static member variable을 만드는 것도 하나의 방법이다.
<But> 지금 상황에서 count 변수는 오직 speak 함수에서만 사용되는 것을 확인할 수 있는데,
이런 경우에 굳이 static 변수를 멤버 변수로 가질 필요 없이
함수 안에 스태틱 변수를 선언하게 되면 접근이 불가능한 더 안전한 코드를 짤 수 있는 것이다.
위의 코드를 컴파일하고 다시 실행해보면 똑같은 결과가 나온다.
static 변수 count가 함수 안으로 들어오게 되어도 이 메모리 공간은 똑같이 static 공간에 선언되어서 이전과 같이 돌아가게 되는데,
차이점은 count 변수가 프로세스 실행 될 때 초기화가 되는지 아니면 speak() 함수가 처음 불러질 때 초기화가 되는가, 즉 초기화의 시점에 대해서 다른 점이 존재한다. 하지만 이 내용은 전문적인 내용이기 대문에 다른 챕터에서 다룰 예정이다.
결론: 두 가지 모든 경우에서 카운트 변수는 static 공간에 선언되기 때문에 object가 달라서 하나의 변수는 공유가 된다.
정리
1. static member function은 이 안에 object를 가리킬 수 있는 this 정보가 없기 때문에 object를 가리킬 수 없다.
그렇기에 그 내부의 멤버 함수와 변수를 사용할 수 없는 것이다.
대신 static member function은 object를 생성하지 않아도 콜 가능하다.
2. static variable의 경우 프로세스 메모리를 그리게 되면 static 공간에 variable이 위치하게 된다.
그렇기에 object가 달라도 하나의 static 메모리 공간을 가리키게 된다.
+만약 static에 대해 더 알고 싶다면 cppreference 에서 관련 자료를 찾아볼 수 있다. C++에서는 static이 여러 의미로 사용이 되니 이 페이지에서 다룬 내용은 static class에 대한 내용이니 참고할 것.
https://en.cppreference.com/w/cpp/language/static
inline static, const static, constexpr static에 대한 정보를 추가로 찾아보면 좋다.
간단하게 정리하고 넘어가면 static 변수가 cont 나 constexpr을 통해서 고정이 된다면 static 변수를 선언할 때 바로 초기화가 가능하다는 내용이 있다.
또한 이러한 static function과 static variable을 사용해서 singleton 디자인 패턴을 구현할 수 있다.
이는 추후 design pattern 페이지에서 더 자세하게 다룰 예정이다.
'모던C++ > OOP' 카테고리의 다른 글
5. function overloading, operator overloading (0) | 2022.08.07 |
---|---|
4. 복사, 이동 생성자 - Copy/move constructor (1) | 2022.08.06 |
3. Member Init List - Class Constructor, Destructor (0) | 2022.08.05 |
1. OOP 란? - 객체 지향 프로그래밍 소개 (0) | 2022.07.24 |