자유 함수가 예상되는 멤버 함수를 어떻게 전달할 수 있습니까?
질문은 다음과 같습니다.이 코드를 고려하십시오.
#include <iostream>
class aClass
{
public:
void aTest(int a, int b)
{
printf("%d + %d = %d", a, b, a + b);
}
};
void function1(void (*function)(int, int))
{
function(1, 1);
}
void test(int a,int b)
{
printf("%d - %d = %d", a , b , a - b);
}
int main (int argc, const char* argv[])
{
aClass a();
function1(&test);
function1(&aClass::aTest); // <-- How should I point to a's aClass::test function?
return 0;
}
어떻게 사용할 수있는 a
'들 aClass::test
에 대한 인수로 function1
? 나는이 일에 갇혀있다.
클래스 멤버에 액세스하고 싶습니다.
함수 포인터를 사용하는 데 아무런 문제가 없습니다. 그러나 비 정적 멤버 함수에 대한 포인터는 일반 함수 포인터와 다릅니다. 함수에 암시 적 인수로 전달되는 객체에서 멤버 함수를 호출해야합니다. 위의 멤버 함수의 서명은 다음과 같습니다.
void (aClass::*)(int, int)
사용하려는 유형보다는
void (*)(int, int)
한 가지 접근 방식은 멤버 함수를 만드는 것으로 구성 될 수 있습니다. static
이 경우 개체를 호출 할 필요가 없으며 유형과 함께 사용할 수 있습니다 void (*)(int, int)
.
당신이 당신의 클래스의 비 정적 멤버에 액세스해야하는 경우 와 당신이 함수는 C 인터페이스의 일부이기 때문에, 예를 들어, 함수 포인터, 고수해야 할, 당신의 최선의 선택은 항상를 전달하는 void*
함수 포인터와 전화를 복용 함수에 에서 객체를 가져온 void*
다음 멤버 함수를 호출 하는 전달 함수를 통해 멤버.
적절한 C ++ 인터페이스에서 함수가 임의의 클래스 유형을 사용하기 위해 함수 객체에 대한 템플릿 인수를 사용하도록하는 것을 원할 수 있습니다. 템플릿 인터페이스를 사용하는 것이 바람직하지 않은 경우 다음과 같은 것을 사용해야합니다 . std::function<void(int, int)>
예를 들어를 사용하여 적절하게 호출 가능한 함수 객체를 만들 수 있습니다 std::bind()
.
클래스 유형 또는 적합한 유형에 대한 템플릿 인수를 사용하는 유형 안전 접근 방식 은 잘못된 유형으로의 캐스트로 인한 오류 가능성을 제거하므로 인터페이스를 std::function<...>
사용하는 것보다 바람직 void*
합니다.
함수 포인터를 사용하여 멤버 함수를 호출하는 방법을 명확히하기 위해 다음 예제가 있습니다.
// the function using the function pointers:
void somefunction(void (*fptr)(void*, int, int), void* context) {
fptr(context, 17, 42);
}
void non_member(void*, int i0, int i1) {
std::cout << "I don't need any context! i0=" << i0 << " i1=" << i1 << "\n";
}
struct foo {
void member(int i0, int i1) {
std::cout << "member function: this=" << this << " i0=" << i0 << " i1=" << i1 << "\n";
}
};
void forwarder(void* context, int i0, int i1) {
static_cast<foo*>(context)->member(i0, i1);
}
int main() {
somefunction(&non_member, 0);
foo object;
somefunction(&forwarder, &object);
}
@Pete Becker의 대답은 괜찮지 만 C ++ 11 class
의 명시 적 매개 변수로 인스턴스를 전달하지 않고도 수행 할 수 있습니다 function1
.
#include <functional>
using namespace std::placeholders;
void function1(std::function<void(int, int)> fun)
{
fun(1, 1);
}
int main (int argc, const char * argv[])
{
...
aClass a;
auto fp = std::bind(&aClass::test, a, _1, _2);
function1(fp);
return 0;
}
멤버 함수에 대한 포인터는 함수에 대한 포인터와 다릅니다. 포인터를 통해 멤버 함수를 사용하려면 포인터 (분명히)와이를 적용 할 객체가 필요합니다. 해당 버전은 그래서 function1
것
void function1(void (aClass::*function)(int, int), aClass& a) {
(a.*function)(1, 1);
}
그리고 그것을 부르기 위해 :
aClass a; // note: no parentheses; with parentheses it's a function declaration
function1(&aClass::test, a);
2011 년부터를 변경할 수 있으면 다음 function1
과 같이 변경 하십시오.
#include <functional>
#include <cstdio>
using namespace std;
class aClass
{
public:
void aTest(int a, int b)
{
printf("%d + %d = %d", a, b, a + b);
}
};
template <typename Callable>
void function1(Callable f)
{
f(1, 1);
}
void test(int a,int b)
{
printf("%d - %d = %d", a , b , a - b);
}
int main()
{
aClass obj;
// Free function
function1(&test);
// Bound member function
using namespace std::placeholders;
function1(std::bind(&aClass::aTest, obj, _1, _2));
// Lambda
function1([&](int a, int b) {
obj.aTest(a, b);
});
}
( 라이브 데모 )
Notice also that I fixed your broken object definition (aClass a();
declares a function).
I asked a similar question (C++ openframeworks passing void from other classes) but the answer I found was clearer so here the explanation for future records:
it’s easier to use std::function as in:
void draw(int grid, std::function<void()> element)
and then call as:
grid.draw(12, std::bind(&BarrettaClass::draw, a, std::placeholders::_1));
or even easier:
grid.draw(12, [&]{a.draw()});
where you create a lambda that calls the object capturing it by reference
You can stop banging your heads now. Here is the wrapper for the member function to support existing functions taking in plain C functions as arguments. thread_local
directive is the key here.
// Example program
#include <iostream>
#include <string>
using namespace std;
typedef int FooCooker_ (int);
// Existing function
extern "C" void cook_10_foo (FooCooker_ FooCooker) {
cout << "Cooking 10 Foo ..." << endl;
cout << "FooCooker:" << endl;
FooCooker (10);
}
struct Bar_ {
Bar_ (int Foo = 0) : Foo (Foo) {};
int cook (int Foo) {
cout << "This Bar got " << this->Foo << endl;
if (this->Foo >= Foo) {
this->Foo -= Foo;
cout << Foo << " cooked" << endl;
return Foo;
} else {
cout << "Can't cook " << Foo << endl;
return 0;
}
}
int Foo = 0;
};
// Each Bar_ object and a member function need to define
// their own wrapper with a global thread_local object ptr
// to be called as a plain C function.
thread_local static Bar_* BarPtr = NULL;
static int cook_in_Bar (int Foo) {
return BarPtr->cook (Foo);
}
thread_local static Bar_* Bar2Ptr = NULL;
static int cook_in_Bar2 (int Foo) {
return Bar2Ptr->cook (Foo);
}
int main () {
BarPtr = new Bar_ (20);
cook_10_foo (cook_in_Bar);
Bar2Ptr = new Bar_ (40);
cook_10_foo (cook_in_Bar2);
delete BarPtr;
delete Bar2Ptr;
return 0;
}
Please comment on any issues with this approach.
Other answers fail to call existing plain C
functions: http://cpp.sh/8exun
I made the member function as static and all works:
#include <iostream>
class aClass
{
public:
static void aTest(int a, int b)
{
printf("%d + %d = %d\n", a, b, a + b);
}
};
void function1(int a,int b,void function(int, int))
{
function(a, b);
}
void test(int a,int b)
{
printf("%d - %d = %d\n", a , b , a - b);
}
int main (int argc, const char* argv[])
{
aClass a;
function1(10,12,test);
function1(10,12,a.aTest); // <-- How should I point to a's aClass::test function?
getchar();return 0;
}
'Programming' 카테고리의 다른 글
jQuery 객체를 어떻게 비교 하시겠습니까? (0) | 2020.08.18 |
---|---|
Flutter 프로젝트의 lint-gradle-api-26.1.2.jar을 찾을 수 없습니다. (0) | 2020.08.18 |
시퀀스에 일치하는 요소가 없습니다. (0) | 2020.08.18 |
Django-DB-Migrations : 보류중인 트리거 이벤트가 있으므로 ALTER TABLE을 사용할 수 없습니다. (0) | 2020.08.18 |
Active Directory에서 사용자 목록을 얻으려면 어떻게해야합니까? (0) | 2020.08.18 |