this
클래스의 멤버 함수를 호출할 때 C++는 어떻게 호출할 객체(인스턴스)를 찾는가
class A
{
public:
int id;
A(int parm) { SetID(parm); }
void SetID(int parm) { id = parm; }
};
int main()
{
A a(1);
a.SetID(2);
cout << a.id << endl;
}
a.SetID(2)는 하나의 int 인자를 가지고 호출되는것 처럼 보이지만,
실제로는 simple.SetID(&a, 2); a의 주소값과 int 두 개의 인자를 가지고 호출한다.
첫번째 파라미터로 전달된 a의 인스턴스의 주소는 이름이 this인 포인터 변수에 저장이 된다.
이 this는 지역변수이다.
이 과정은 컴파일러에 의해서 추가된다.
컴파일러 입장에서 본다면
class A
{
public:
int id;
A(A* const this, int parm)
{
this->SetID(parm);
}
void SetID(A* const this, int parm)
{
this->id = parm;
}
};
int main()
{
A a(&a, 2);
}
다음과 같이 컴파일 되는것이다.
. 은 클래스의 멤버를 직접 접근
->은 포인터를 통해 멤버를 접근
this는 포인터 변수이므로 ->를 사용해 멤버변수에 접근하는것
---------------------------------------------------------------------
그런데 this포인터를 굳이 만들필요가있었을까?
클래스의 멤버변수들은 객체가 만들어질때마다 메모리에 할당된다.
하지만 함수와 같이 반복호출하고 크기가 큰 것들은 메모리에 할당하면 낭비가 심하다
예를들어 A클래스 인스턴스 a1 a2 a3 a4 a5가 있다고하면 이들은 모두 각각 id라는 멤버변수를 가져 메모리에 할당된다.
하지만 생성자나 SetID함수 경우, 인스턴스 모두 공통적으로 사용할 수 있고 똑같은 함수를 굳이 메모리에 인스턴스마다 할당할 필요가 없기때문에 함수는 한번만 메모리에 할당하고 인스턴스의 주소값을 this 포인터에 보내주어 어떤 인스턴스가 함수를 호출하였는지 알게하는것이다.
----------------------------------------------------------------------
연산자 오버로딩
기존의 연산자를 새로 재정의하여 사용자 정의 클래스로 사용하는 것
오버로드 된 연산자는 함수로 구현된다.
int main()
{
A a1(2);
A a2(3);
A a3 = a1 + a2;
}
A클래스의 a1의 id와 a2의 id를 더한 a3 인스턴스를 만들고싶다.
그렇지만 A클래스의 덧셈은 정의되어있지않아 오류가 날 것이다.
class A
{
private:
int id;
public:
A(int parm)
{
this->SetID(parm);
}
void SetID(int parm)
{
this->id = parm;
}
A operator + (A& a)
{
this->id += a.id;
return A(id);
}
friend ostream &operator<<(ostream &, const A &);
};
ostream &operator<<(ostream &os, const A &a)
{
os << "id: " << a.id;
return os;
}
int main()
{
A a1(2);
A a2(3);
A a3 = a1 + a2;
cout << a3;
}
함수의 이름을 operator로 사용함으로써 컴파일러에게 연산자 오버로드 함수인것을 명시한다.
a1이 오버로드된 + 연산자 함수를 호출하였고, a2가 A &a 인자값으로 넘겨받아지는 것이다.
또한 cin, cout의 << 연산자 >> 연산자 오버로딩도 가능하다. (cout은 ostream 타입의 객체)
우선 ostream 클래스 내부라고한다.
ostream& operator<<(bool& val);
ostream& operator<<(short& val);
ostream& operator<<(unsigned short& val);
ostream& operator<<(int& val);
ostream& operator<<(unsigned int& val);
ostream& operator<<(long& val);
ostream& operator<<(unsigned long& val);
ostream& operator<<(float& val);
ostream& operator<<(double& val);
ostream& operator<<(long double& val);
ostream& operator<<(void* val);
A객체의 private 멤버인 id에 접근 할 수 있도록 A 클래스 내부에 friend 함수를 지정해 주었고, ostream과 A클래스의 인스턴스의 주솟값을받아 id를 출력하도록 재정의해주었다.
'프로그래밍 > C++' 카테고리의 다른 글
표준 템플릿 라이브러리(STL) - vector 메모리/ iterator , 표준 라이브러리 - string (0) | 2022.05.03 |
---|---|
header / namespace (1) | 2022.05.02 |
멤버 초기화 리스트, 이니셜라이저 (0) | 2022.04.13 |
const / constexpr / #define (0) | 2022.04.12 |
C++ 상속 (0) | 2022.04.08 |