본문 바로가기

교육 노트/C++ 심화강의

[C++ 때려잡기] C++ 심화강의 5 this 포인터

2018/08/27 - [교육 노트/C++ 심화강의] - [C++ 때려잡기] C++ 심화강의 1 객체 지향 프로그래밍과 클래스

2018/08/27 - [교육 노트/C++ 심화강의] - [C++ 때려잡기] C++ 심화강의 2 접근 한정자

2018/08/27 - [교육 노트/C++ 심화강의] - [C++ 때려잡기] C++ 심화강의 3 생성자와 소멸자

2018/08/29 - [교육 노트/C++ 심화강의] - [C++ 때려잡기] C++ 심화강의 4 복사 생성자와 깊은 복사


캐릭터 클래스에 hp를 설정하는 setHp를 다시 만들었다고 해보자

    void setHp(int _hp)
    {
        hp = _hp;
    }

이런식으로 구현하였다.


hp = _hp는 내 클래스의 맴버 변수 hp 를 파라미터로 받은 _hp 로 설정하는것이다.

근데 파라미터 의 _hp에서 앞에 _가 너무너무 신경쓰여 미칠지경이라 정말정말 어떻게든 파라미터명으로 _hp가 이날 그냥 hp로 받고싶다.


    void setHp(int hp)
    {
        hp = hp;
    }

이렇게 말이다.

하지만 C++에서는 이렇게되면 저 함수에서 hp라는 것은 더 가까이있는 파라미터의 hp만을 의미하게 된다

즉 파라미터hp를 파라미터hp로 초기화하는 쓸데없는 함수가 되어버린다.



1. this 포인터

C++에서는 자기자신 객체를 가르키는 this포인터라는것을 제공한다.

즉 위의 setHP 코드에서 자신의 맴버변수 hp인것은 자신을 가르키는 포인터를 이용해서 사용하면 되는것이다.


    void setHp(int hp)
    {
        this->hp = hp;
    }

다음과 같이 쓰면 자신의 맴버변수 hp를 파라미터 hp로 초기화하는것이 가능하다.

ps. ->는 잠시후 설명



그럼 this포인터가 정말 자기 자신을 가르키는지 확인해보자


#include <iostream>
using namespace std;

class Character
{
public:

public:
    Character* getThis();
};


Character* Character::getThis()
{
    return this;
}


int main()
{
    Character mario;        
    Character* marioPtr = &mario;

    cout << "marioPtr: " << marioPtr << endl;
    cout << "marioThis: " << mario.getThis() << endl;


    return 0;
}


정말 자기 자신을 가르킨다


그럼 이 this포인터는 왜 필요한것일까?

저런 파라미터 이름과 맴버변수 이름을 같게 하고싶은 강박증 걸린사람을 위해서 this포인터라는 거창한 개념을 만든것일까?

this포인터는 체이닝과 C++ 의 함수 동작원리와 관련이있다.

체이닝은 여기서 패스하도록하고

C++에서 함수를 선언하고 정의하면 메모리에 해당 함수에 대한 코드가 할당된다.

그리고 그 함수가 호출되면 해당 메모리로 이동하여 함수 기능을 수행하고 다시 호출한 지점으로 돌아오게 된다.



즉 함수 내용자체는 1번만 만들어지고 두고두고 사용하는것이다.

클래스의 맴버 변수들은 객체가 만들어질때마다 해당 변수들이 메모리에 할당되지만

함수와 같이 방대한 내용을, 그것도 같은 내용인데 굳이 여러번 메모리에 올릴필요가 없기때문에

어딘가에 1번 메모리에 올리고 내부적으로 각 객체의 this 포인터를 함수에게 넘겨주어 어떤 객체가 해당 함수를 호출했는지 알도록 하는것이다.



2. ->

. (점)은 객체에 내부에 접근할때 사용했다. 근데 위에 this->hp는 -> 를 사용했다

여기서 this는 포인터라는 점이다. 즉 포인터를 통하여 접근할때는 ->를 사용한다.

#include <iostream>
using namespace std;

class Character
{
public:
    Character(int _hp)
    {
        hp = _hp;
    }

private:
    int hp;
public:
    int getHp();
};


int Character::getHp()
{
    return hp;
}


int main()
{
    Character mario(100);
    Character* marioPtr = &mario;

    cout << mario.getHp() << endl;
    cout << marioPtr->getHp() << endl;
    

    return 0;
}


-> 는 해당 포인터가 가르키고 있는 객체의 내부에 접근하는것이다


그래서 다음 두 코드는 동일한 내용이다.


    cout << marioPtr->getHp() << endl;
    cout << (*marioPtr).getHp() << endl;


728x90