파이썬의 경우 self (C++ 의 this) 를 명시적으로 써준다.
그리고 객체.함수(파라미터1, 파라미터2) 에서 묵시적으로 객체 자신을 첫 파라미터로 넘기게 되는데 (바운드)
따라서 클래스명.함수(객체, 파라미터1, 파라미터2) 와 동일하다. (언바운드)
1
2
3
4
5
6
7
|
class A(object):
def fun(self):
print("fun")
a = A()
a.fun()
A.fun(a)
|
cs |
그런데 C++ 에서는 this 포인터를 묵시적으로 넘긴다고 배웠는데 (숨겨진 this 포인터)
그럼 파이썬마냥 A::fun(*a) 와 같이 호출 할 수 있어야 하는것 아닌가?
근데 안된다. GCC는 모르겠는데 일단 ViusalC++ 에서는 안된다.
뭐 안되는건 안되는거고 실제로 This pointer가 파라미터로 넘어가긴 하는지 확인해보기 위하여
간단한 코드를 제작하고 디스어셈블리창을 통해 확인해보았다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
#include <iostream>
using namespace std;
class A
{
public:
void Fun(int, int) {}
static void Fun(A* a, int, int) {};
};
void Fun(A* a, int, int) {}
int main()
{
A a;
cout << "Reg" << endl;
Fun(&a, 1, 2);
a.Fun(1, 2);
A::Fun(&a, 1, 2);
return 0;
}
|
cs |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
//Fun(&a, 1, 2);
011F293B push 2
011F293D push 1
011F293F lea eax,[a]
011F2942 push eax
011F2943 call Fun (011F16AEh)
011F2948 add esp,0Ch
//a.Fun(1, 2);
011F294B push 2
011F294D push 1
011F294F lea ecx,[a]
011F2952 call A::Fun (011F16B3h)
//A::Fun(&a, 1, 2);
011F2957 push 2
011F2959 push 1
011F295B lea eax,[a]
011F295E push eax
011F295F call A::Fun (011F16A9h)
011F2964 add esp,0Ch
|
cs |
다음과 같이 VC++ 의 경우, 스텍에 차곡차곡 넣어서 넘기는 일반 함수나 Static 함수 와 달리 맴버 함수에서 This Pointer(정확히는 객체 자신의 주소)를 ECX 레지스터를 이용해서 기억한다. (ECX 는 Counter용 아닌가;;)
뭐 결과론적으로 맴버 함수실행시 ECX 레지스터 에서 this pointer에 복사하기 때문에 넘기지 않는것은 아니지만 흔히 말하는 클래스명.함수(객체, 파라미터1, 파라미터2) 처럼 넘어가는것은 아니다.
이를 찾아보니..
VC++에서는 ECX 레지스터를 이용해서 넘기는것이 기본이고 __stdcall 키워드를 이용하면 우리가 아는것처럼 동작하게 된다고 한다. 참고로 G++ 은 최적화를 쓰지않으면 우리가 아는것처럼 동작한다고 한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
#include <iostream>
using namespace std;
class A
{
public:
void __stdcall Fun(int, int) {}
static void Fun(A* a, int, int) {};
};
void Fun(A* a, int, int) {}
int main()
{
A a;
cout << "Reg" << endl;
Fun(&a, 1, 2);
a.Fun(1, 2);
A::Fun(&a, 1, 2);
return 0;
}
|
cs |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
//Fun(&a, 1, 2);
0084293B push 2
0084293D push 1
0084293F lea eax,[a]
00842942 push eax
00842943 call Fun (08416AEh)
00842948 add esp,0Ch
//a.Fun(1, 2); , __stdcall
0084294B push 2
0084294D push 1
0084294F lea eax,[a]
00842952 push eax
00842953 call A::Fun (08416B8h)
//A::Fun(&a, 1, 2);
00842958 push 2
0084295A push 1
0084295C lea eax,[a]
0084295F push eax
00842960 call A::Fun (08416A9h)
00842965 add esp,0Ch
|
cs |
보시다시피 어셈블리어 단에서 다른 함수와 동일하게 동작한다.
하지만 그렇다고 A::fun(*a) 처럼 사용은 안된다 ㅜ 이러게 사용하는 방법을 아는사람이 있다면 알려주시길 ㅜㅜ
'프로그래밍 언어 노트 > C++ | Modern C++' 카테고리의 다른 글
[Modern C++] C++ 코루틴 (0) | 2019.07.09 |
---|---|
[C++] 숨겨진 This pointer 는 어떻게 넘어 가는가~ 2 (0) | 2019.07.09 |
[모던 C++] C++의 아버지 스트로스트눕이 해주는 모던 C++ 이야기 (0) | 2019.06.01 |
[Visual Studio] Template의 intellisence (0) | 2018.10.07 |
[C++] C++ 의 RTTI, typeid (0) | 2018.10.01 |