포스트

정적 멤버 함수와 this 포인터

객체 지향 프로그래밍(OOP)에서 중요한 개념은 클래스와 객체입니다. 클래스는 객체를 생성하는 설계도로, 클래스로부터 생성된 실체를 인스턴스라고 합니다.

이러한 인스턴스는 자신을 가리키는 특별한 포인터, this 포인터를 가지고 있습니다.
이 포인터는 인스턴스의 멤버에 접근할 수 있게 하지만, 정적 멤버 함수에서는 사용될 수 없습니다.

정적 멤버 함수 (Static Member Functions)

클래스 내에서 static 키워드를 사용하여 정적 멤버 변수정적 멤버 함수를 정의할 수 있습니다.

정적 멤버 함수는 클래스 자체에 속해 있으며, 특정 인스턴스에 종속되지 않고, 모든 인스턴스가 공유하는 공간에 위치합니다.

정적 멤버 함수

정적 멤버 변수와 정적 멤버 함수에 대한 자세한 글은 먼저 적어둔 적이 있으므로 링크를 걸어두겠습니다.

[static 키워드] 02_정적 멤버 변수

[static 키워드] 03_정적 멤버 함수

그런데 사실, 비정적 멤버 함수와 정적 멤버 함수는 모두 메모리의 코드 영역(TEXT)에 저장됩니다.

다만, 논리적인 정의가 다를 뿐입니다.

  • 정적 멤버 함수
    • 클래스 자체에 속하며, 클래스의 모든 인스턴스가 공유하는 함수입니다.
    • 특정 객체의 인스턴스와 무관하게 클래스 자체에서 호출될 수 있습니다.
  • 비정적 멤버 함수
    • 특정 객체의 인스턴스와 연관되어 해당 객체의 상태를 조작하는 데 사용됩니다.

즉, 비정적 멤버 함수는 특정 인스턴스의 상태를 조작하기 위한 함수이고, 정적 멤버 함수는 인스턴스와 무관하게 클래스 단위로 클래스에 관련된 유틸리티 함수나 클래스 전역 데이터를 처리하는 데 사용하는 함수입니다.

클래스 멤버에 대한 메모리 구조

  • 코드 영역 (TEXT)
    • 모든 함수(정적 멤버 함수비정적 멤버 함수 모두)가 저장됩니다.
  • 데이터 영역 (BSS, DATA)
    • 정적 멤버 변수가 저장됩니다.
  • 힙 혹은 스택
    • 각 인스턴스의 비정적 멤버 변수가 저장됩니다.
    • 이때, this 포인터를 저장하고, 비정적 멤버 함수를 실행할 때 this 포인터를 통해 접근합니다.

this 포인터

정리하자면, 하나의 클래스에서 생성된 인스턴스는 각각 독립된 메모리 공간에 자신만의 비정적 멤버 변수를 가지지만, 정적 멤버 함수비정적 멤버 함수는 모든 인스턴스가 공유합니다.

때문에, 모든 비정적 멤버 함수는 자신을 호출한 객체가 무엇인지 정확히 파악할 수 있도록 this 포인터를 사용합니다.

this 포인터는 호출된 비정적 멤버 함수에 숨겨진 인자로 전달되며, 함수를 호출한 자신의 인스턴스 주소를 저장합니다.

정적 멤버 함수와 this 포인터

이제 서두에서 나왔던 this 포인터를 정적 멤버 함수에서 사용할 수 없는 이유입니다.

모든 멤버 함수는 코드 영역에 저장되지만, 비정적 멤버 함수의 목적이 객체의 상태를 조작하는 데 사용하는 것입니다.
따라서, 객체의 상태를 보고, 조작할 수 있게끔 해당 데이터가 존재하는 주소를 필요로 하는데, 이때 사용되는 것이 this 포인터 입니다.

정적 멤버 함수는 인스턴스와 무관하게 클래스 단위로 클래스에 관련된 유틸리티 함수나 클래스 전역 데이터를 처리하는 데 사용하는 함수입니다.
정적 멤버 함수가 this 포인터를 받지 않는 이유는, 이들 함수가 인스턴스와 독립적으로 동작하도록 설계되었기 때문입니다.

예를 들어, 클래스 단위로 동작해야 하는 함수에 this 포인터를 사용하도록 한다면, 그것은 코드의 로직에 혼란을 주고, 잠재적인 오류의 원인이 될 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class MyClass
{
public:
    static int staticVar;

    static void staticFunc()
    {
        // 이 함수는 클래스 단위로 독립적으로 호출할 수 있어야 하며, 인스턴스와 무관하게 동작하도록 설계되었습니다.

        // 만약 이후 수정하는 사람이, 이 사실을 잊고 이곳에 'this' 포인터를 사용한다면?
    }
};

int MyClass::staticVar = 10;

int main()
{
    MyClass::staticFunc(); // 객체 없이 호출 가능
}


참고

[static 키워드] 02_정적 멤버 변수

[static 키워드] 03_정적 멤버 함수

메모리 구조 (Memory Structure)

이 기사는 저작권자의 CC BY-NC-ND 4.0 라이센스를 따릅니다.