英文:
Is it possible to pass class method instead of function and provide diffrent this pointer
问题
void f(int(*fp)(C*,int)){
C c(20);
std::cout << fp(&c, 5) << std::endl;
}
英文:
#include <iostream>
class C{
private:
int a;
public:
C(int a):a(a){};
int m(int b){
return a + b;
}
};
void f(int(*fp)(C*,int)){
C c(20);
std::cout << fp(&c, 5) << std::endl;
}
int main(int argc, char *argv[]) {
C c(10);
f(reinterpret_cast<int(*)(C*,int)>(c.m)); //has to be function pointer
return 0;
}
This cast obviously doesn't work.
It can't be static method.
f
needs to have this signature.
答案1
得分: 2
以下是翻译好的部分:
当你需要传递指针给一个方法时,可以像这样做:
```cpp
#include <iostream>
class C {
private:
int a;
public:
C(int a) : a(a) {}
int add(int b) { return a + b; }
int sub(int b) { return a - b; }
};
void f(int (C::*fp)(int)) {
C c(20);
std::cout << (c.*fp)(5) << std::endl;
}
int main() {
f(&C::add);
f(&C::sub);
}
上面的示例在函数 f
中仍然使用了硬编码的 C
实例。如果你想要在不同的 C
实例上调用方法,那么你应该传递一个对象的引用(或指针):
void f(C &c, int (C::*fp)(int)) {
std::cout << (c.*fp)(5) << std::endl;
}
int main() {
C foo(10), bar(20);
f(foo, &C::add);
f(foo, &C::sub);
f(bar, &C::add);
f(bar, &C::sub);
}
关于这段代码:
void f(int(*fp)(C*,int))
f
函数需要有这个签名。
嗯,如果你写适配器函数并使用 int (*fp)(C*, int)
这个签名,你还是可以做到这一点。你仍然需要从某个地方获取 C*
的值。它不能是隐式的。所以,回到你最初的例子,在函数 f
中硬编码了 C(20)
:
#include <iostream>
class C {
private:
int a;
public:
C(int a) : a(a) {}
int add(int b) { return a + b; }
int sub(int b) { return a - b; }
};
// 带有适当签名的适配器函数
int add(C* c, int b) { return c->add(b); }
int sub(C* c, int b) { return c->sub(b); }
void f(int (*fp)(C*, int)) {
C c(20);
std::cout << fp(&c, 5) << std::endl;
}
int main() {
f(add);
f(sub);
}
英文:
When you need to pass a pointer to a method, do it like this:
#include <iostream>
class C {
private:
int a;
public:
C(int a) : a(a) {}
int add(int b) { return a + b; }
int sub(int b) { return a - b; }
};
void f(int (C::*fp)(int)) {
C c(20);
std::cout << (c.*fp)(5) << std::endl;
}
int main() {
f(&C::add);
f(&C::sub);
}
The above example still uses a C
instance hard-coded in the function f
. If you want to call the method on different instances of C
, then you should instead pass a reference (or pointer) to the object:
void f(C &c, int (C::*fp)(int)) {
std::cout << (c.*fp)(5) << std::endl;
}
int main() {
C foo(10), bar(20);
f(foo, &C::add);
f(foo, &C::sub);
f(bar, &C::add);
f(bar, &C::sub);
}
Regarding this:
>
> void f(int(*fp)(C*,int))
>
> f needs to have this signature.
Well, you can sort-of do this if you write adapter functions with the signature int (*fp)(C*, int)
. You still need to get the C*
value from somewhere. It cannot be implicit. So, going back to your original example that hard-codes C(20)
in the function f
:
#include <iostream>
class C {
private:
int a;
public:
C(int a) : a(a) {}
int add(int b) { return a + b; }
int sub(int b) { return a - b; }
};
// Adapters with the appropriate signature
int add(C* c, int b) { return c->add(b); }
int sub(C* c, int b) { return c->sub(b); }
void f(int (*fp)(C*, int)) {
C c(20);
std::cout << fp(&c, 5) << std::endl;
}
int main() {
f(add);
f(sub);
}
答案2
得分: 0
Old school C-style function pointers aren't the C++ way to pass functions. If you're still working with C libraries, you're stuck, but if you control the code used, there are better ways.
This is a cut & paste from some of my code:
#include <functional>
...
typedef std::function<void(HTTPServerRequest &, HTTPServerResponse &)> Callback;
By using std::function
you are enabling the use of non-static class methods or lambdas. I tend to prefer lambdas, because otherwise you also have to use std::bind
, and I think that's ugly.
So if I can do this to define a Route
constructor.
Route(const std::string &m, const std::string &p, const std::string &d, Route::Callback );
And I can pass that callback argument as:
[=](HTTPServerRequest &request, HTTPServerResponse &response) {
handleRequest(request, response);
}
(That's a lambda.) If I'm using this from some class, and handleRequest is a non-static method in that class, this works, and it's pretty clean.
You can also pass in C-style function pointers or use std::bind()
.
英文:
Old school C-style function pointers aren't the C++ way to pass functions. If you're still working with C libraries, you're stuck, but if you control the code used, there are better ways.
This is a cut & paste from some of my code:
#include <functional>
...
typedef std::function<void(HTTPServerRequest &, HTTPServerResponse &)> Callback;
By using std::function
you are enabling the use of non-static class methods or lambdas. I tend to prefer lambdas, because otherwise you also have to use std::bind, and I think that's ugly.
So if I can do this to define a Route
constructor.
Route(const std::string &m, const std::string &p, const std::string &d, Route::Callback );
And I can pass that callback argument as:
[=](HTTPServerRequest &request, HTTPServerResponse &response) {
handleRequest(request, response);
}
(That's a lambda.) If I'm using this from some class, and handleRequest is a non-static method in that class, this works, and it's pretty clean.
You can also pass in C-style function pointers or use std::bind()
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论