C++ Chapter 8.11 : static 정적 멤버 함수
카테고리: Cpp
태그: Cpp Programming
인프런에 있는 홍정모 교수님의 홍정모의 따라 하며 배우는 C++ 강의를 듣고 정리한 필기입니다. 😀
🌜 [홍정모의 따라 하며 배우는 C++]강의 들으러 가기!
chapter 8. 객체 지향의 기초 : static 정적 멤버 함수
🔔 static 멤버 함수란?
staitc
멤버 변수처럼- 객체 이름은 물론이고 클래스 이름만으로도 접근이 가능하다.
- 객체와 독립적이다. 객체 생성과 상관 없다.
- 따라서 멤버 변수는 객체가 생성되야 메모리를 할당받기 때문에
static
멤버 함수 내에서는 멤버 변수를 사용할 수 없다. - 그러나 미리 전역에서 메모리가 할당되는 static 멤버 변수는 사용이 가능하다.
- 따라서 멤버 변수는 객체가 생성되야 메모리를 할당받기 때문에
class Something
{
private:
int noramal_value = 99; // 일반 멤버 변수
static int static_value; // static 멤버 변수
public:
static void Func() // ⭐ static 멤버 함수
{
int a = 1024; // Func()내의 일반 지역 변수
cout << a << endl;
// cout << noramal_value << endl; 👈👈 💥에러!!!💥 일반 멤버 변수는 사용할 수 없다.
cout << static_value << endl; // static 멤버 변수는 사용 가능
}
};
int Something::static_value = 777;
int main()
{
Something::Func(); // 객체 생성 없이 바로 클래스 이름으로 호출 가능
/* 👆 1024와 777을 출력한다. */
return 0;
}
🔔 static 멤버 함수를 사용하는 이유
객체 생성 여부와 상관없이 바로 클래스 이름으로 접근하고 싶을 때 사용하지만 주로 private인 static 멤버 변수에 접근하려 할 때 많이 쓰인다.
staitc
멤버 변수는 모든 객체들이 사용하고 공유해야하는데private
이라면 외부에서 직접 접근하고 사용할 수가 없다.private
인 멤버 변수들은 멤버 함수들에서만 접근이 가능하다는 특징이 있다.
static
멤버 함수 를 통해서private
한staitc
멤버 변수 에 간접 접근할 수 있도록 구현할 수 있다.- 마치 getter, setter 접근함수처럼!
class Something
{
private:
static int static_value; // private한 static 멤버 변수
public:
static int getValue() // ⭐ static 멤버 함수
{
return static_value;
}
};
int Something::static_value = 777;
int main()
{
// cout << Something::static_value << endl; 👈👈 💥에러!💥 private이므로 직접 접근 불가능
cout << Something::getValue() << endl; // 777 출력. 클래스 이름으로 호출했을 때.
Something s;
cout << s.getValue() << endl; // 777 출력. 객체 이름으로 호출했을 때.
return 0;
}
이처럼 private한 staitc 멤버 변수를 직접 접근할 수는 없지만 static 멤버 함수 getValue()를 통하여 간접적으로 staitc 멤버 변수를 리턴받을 수 있다.
🔔 static 멤버 함수는 this 포인터를 사용할 수 없다.
this
포인터는 객체인 자기 자신의 주소, 즉 객체의 주소를 담고 있기 때문에 객체가 생성되야지만 사용할 수 있다.- static 멤버 함수는 객체들의 생성과 무관하며 언제 어디서든 클래스 이름으로도 접근이 가능해야 하기 때문에
- static 멤버 함수 내부에서는 this 포인터를 사용할 수 없다.
- static 멤버 함수 내부에서 일반 멤버 변수를 사용할 수 없었듯이.
- 이에 더해 this포인터로 접근할 수 있는 모든 것을 하지 못 한다.
- 같은 객체 내의 멤버 변수나 멤버 함수는 접근하지 못한다. 눈에 보이지 않아도 이들을 접근할 땐
this->
가 숨어있는 것이나 마찬가지기 때문에.
- 같은 객체 내의 멤버 변수나 멤버 함수는 접근하지 못한다. 눈에 보이지 않아도 이들을 접근할 땐
class Something
{
private:
static int static_value; // static 멤버 변수
public:
static int getValue() // ⭐ static 멤버 함수
{
return this -> static_value; // 💥에러💥
}
int temp() // ⭐ 일반 멤버 함수
{
return this -> static_value; // 문제 없다.
}
};
- static 멤버 함수인 getValue()에선
this
를 사용할 수 없다. - 일반 멤버 함수인 temp()에선
this
를 사용할 수 있다.
멤버 함수 포인터
함수 포인터 포스트에서 일반 함수는 함수 이름
에 함수의 주소값이 들어있다는 것을 공부했었다. 그러나 멤버 함수의 포인터는 조금 다르다.
멤버 함수의 포인터는
& 클래스이름 :: 함수이름
으로 접근해야 한다.
class Something
{
public:
int temp() { return 1; }
};
int main()
{
Something s1;
Something s2;
int (Something::*fptr_1)() = s1.temp; // 💥에러💥
int (Something::*fptr_2)() = &Something::temp; // 문제 없다.
}
- int (Something::*fptr_1)() =
s1.temp
;- 💥에러💥
- 멤버 함수의 포인터는 이렇게
s1.temp
함수 이름으로 접근하면 안된다.
- 멤버 함수의 포인터는 이렇게
- 💥에러💥
- int (Something::*fptr_2)() =
&Something::temp
;- 멤버 함수의 포인터는 이렇게
& 클래스이름 :: 함수이름
으로 &와 클래스 이름으로 접근해야 한다.
- 멤버 함수의 포인터는 이렇게
- 이유
- 멤버 변수는 각 객체들마다 따로 메모리를 가져 주소가 다르지만
- 멤버 함수는 객체마다 함수 메모리를 따로 갖는 방식이 아니기 때문이다.
- 멤버 함수는 어딘가 한군데에 저장되어 있고 각 객체마다 그 공간에 동일하게 접근하여 각자의 다른 데이터로 사용하는 방식이다.
- 따라서 일반 함수의 주소와는 다르게 멤버 함수의 주소를 받아와야 한다.
- 그럴려면 속해있는 클래스가 어디인지 알려주어야 한다.
&Something::
- 그럴려면 속해있는 클래스가 어디인지 알려주어야 한다.
함수 포인터로 함수 실행하기 : 일반 멤버 함수
temp()는 Something 클래스의 일반 멤버 함수라고 하자.
Something s;
int (Something::*fptr_1)() = &Something::temp;
cout << (s.*fptr_1)() << endl; // 함수 포인터로 s 객체의 temp 함수 실행
- int (Something::*fptr_1)()
- 포인터 선언시
Something::
를 꼭 붙여주어야 한다.
- 포인터 선언시
- 함수 포인터로 일반 멤버 함수를 실행할 때는 꼭
(s.*fptr_1)()
처럼 객체로 접근해 주어야 한다.- fptr_1은 객체에 종속되는 일반 멤버 함수를 참조하고 있기 때문에 단독으로 호출할 수 없기 때문이다.
- 멤버 함수 포인터는 객체의 내용물을 참조하기 때문에
(객체.*멤버함수포인터)(매개변수)
로 사용해야 한다.- 포인터로 객체를 참조하고 있다면
(객체포인터->*멤버함수포인터)(매개변수)
- 포인터로 객체를 참조하고 있다면
함수 포인터로 함수 실행하기 : static 멤버 함수
getValue()는 Something 클래스의 static 멤버 함수라고 하자.
Something s;
int (*fptr_2)() = &Something::temp;
cout << fptr_2() << endl; // 함수 포인터로 s 객체의 temp 함수 실행
- int (*fptr_2)()
- static 멤버 함수는 객체와 무관하게 연산이 이루어 지기 때문에 일반 함수 포인터로 취급 받는다.
- 따라서 포인터 선언시 Something:: 을 떼고 일반 함수처럼 int (*fptr_2)()로만 선언해준다.
- static 멤버 함수는 객체와 무관하게 연산이 이루어 지기 때문에 일반 함수 포인터로 취급 받는다.
- fptr_2()
- 일반 함수 포인터로 취급되기에 이렇게 단독 호출할 수 있다.
🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄
댓글 남기기