개발을 하다가 std::function이나 c타입의 함수 포인터에 클래스의 멤버 함수(=메소드)를
할당해야 할 때가 있다. 하지만 typeid로 멤버 함수의 타입을 보면 타입이 조금 다르다.
#include <iostream>
using namespace std;
class A {
public:
A() {
cout << typeid(&A::printHello).name() << '\n';
}
public:
void printHello() {
cout << "Hello\n";
}
};
int main() {
A test;
}
/*
결과 : void (A::*)(void) __ptr64
원하는 결과 : void (void)
*/
멤버 함수 타입을 보면 이상한 게 추가로 붙어 있다. 이를 통해 클래스의 멤버 함수는 일반적인 함수와 형식이 다르다는 것을 알 수 있는데, static 함수는 또 일반적인 함수로 인식한다. 하지만 우리가 메소드를 사용해야 하는 이유는 멤버변수에 접근을 할 수 있는 함수이기 때문이다.
이건 은근 간단하게 해결이 가능하다. 바로 std::bind를 사용하면 된다.
std::bind함수는 '함수 -> 객체'로 바꿔주는 함수로, 변환하기 전에 원하는 매개변수 자리나 값을 미리 정해 놓을 수 있다.
이 std::bind가 함수를 객체로 바꿔주는 기능 말고도, 멤버 함수를 일반 함수 객체로 바꿔주는 것도 가능하다.
// Bind의 일반적인 사용
int Add(int a, int b) {
return a + b;
}
int main() {
function<int()> add1 = bind(Add, 10, 20);
cout << add1() << '\n';
function<int(int)> add2 = bind(Add, 10, std::placeholders::_1);
cout << add2(30) << '\n';
function<int(int, int)> add3 = bind(Add, placeholders::_1, placeholders::_2);
cout << add3(20, 30) << '\n';
}
// 클래스에서 멤버 함수를 일반함수로 변환
void print(function<string()> fs) {
cout << fs() << '\n';
}
class A {
public:
A() {
print(&A::GetHello); // error
print(bind(&A::GetHello, this));
}
public:
string GetHello() { return "Hello!"; }
};
int main() {
A test;
}
std::bind(함수, 객체_포인터, std::placeholders::_1, ...) 이런식으로 사용할 수도 있다.
std::bind이외에도 람다표현식을 사용하는 것도 가능하다.
print([this]() {
return GetHello();
});
'C++' 카테고리의 다른 글
[C++] vcpkg 라이브러리 패키징 (0) | 2024.08.07 |
---|---|
[C++] 제대로 알고 사용하자. atd::async (0) | 2024.07.13 |
[C++] C++에서 라이브러리를 관리해보자 (0) | 2024.06.27 |
[C++/Unreal] 커스텀 RPC 구현 기록 (0) | 2024.05.31 |
[C++] 에러코드를 메세지로 format하기 (0) | 2023.11.17 |